• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Unleash / unleash-edge / 17914520369

22 Sep 2025 11:58AM UTC coverage: 68.901% (-0.02%) from 68.92%
17914520369

Pull #1175

github

web-flow
Merge 0b359f9c3 into fa44c3fee
Pull Request #1175: fix: readded hosting to EdgeInstanceData

24 of 37 new or added lines in 3 files covered. (64.86%)

75 existing lines in 3 files now uncovered.

7351 of 10669 relevant lines covered (68.9%)

6987.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/crates/unleash-edge/src/lib.rs
1
use crate::edge_builder::build_edge_state;
2
use crate::offline_builder::build_offline_app_state;
3
use ::tracing::info;
4
use axum::Router;
5
use axum::middleware::{from_fn, from_fn_with_state};
6
use axum::routing::get;
7
use chrono::Duration;
8
use std::env;
9
use std::sync::{Arc, LazyLock};
10
use tokio::sync::RwLock;
11
use tower::ServiceBuilder;
12
use tower_http::compression::CompressionLayer;
13
use ulid::Ulid;
14
use unleash_edge_auth::token_validator::TokenValidator;
15
use unleash_edge_cli::{AuthHeaders, CliArgs, EdgeMode};
16
use unleash_edge_delta::cache_manager::DeltaCacheManager;
17
use unleash_edge_feature_cache::FeatureCache;
18
use unleash_edge_feature_refresh::HydratorType;
19
use unleash_edge_http_client::{ClientMetaInformation, HttpClientArgs, new_reqwest_client};
20
use unleash_edge_metrics::axum_prometheus_metrics::{
21
    PrometheusAxumLayer, render_prometheus_metrics,
22
};
23
use unleash_edge_persistence::EdgePersistence;
24
use unleash_edge_types::metrics::instance_data::EdgeInstanceData;
25
use unleash_edge_types::metrics::instance_data::Hosting::SelfHosted;
26
use unleash_edge_types::{BackgroundTask, EdgeResult, EngineCache, TokenCache};
27

28
pub mod edge_builder;
29
pub mod health_checker;
30
mod middleware;
31
pub mod offline_builder;
32
pub mod ready_checker;
33
pub mod tls;
34
pub mod tracing;
35

36
static SHOULD_DEFER_VALIDATION: LazyLock<bool> = LazyLock::new(|| {
×
37
    env::var("EDGE_DEFER_TOKEN_VALIDATION")
×
38
        .map(|v| v == "true" || v == "1")
×
39
        .unwrap_or(false)
×
UNCOV
40
});
×
41

42
type CacheContainer = (
43
    Arc<TokenCache>,
44
    Arc<FeatureCache>,
45
    Arc<DeltaCacheManager>,
46
    Arc<EngineCache>,
47
);
48
pub type EdgeInfo = (
49
    CacheContainer,
50
    Arc<TokenValidator>,
51
    HydratorType,
52
    Option<Arc<dyn EdgePersistence>>,
53
);
54

55
pub async fn configure_server(args: CliArgs) -> EdgeResult<(Router, Vec<BackgroundTask>)> {
×
56
    let app_id: Ulid = Ulid::new();
×
NEW
57
    let hosting = std::env::var("EDGE_HOSTING")
×
NEW
58
        .map(Into::into)
×
NEW
59
        .unwrap_or(SelfHosted);
×
NEW
60
    let edge_instance_data = Arc::new(EdgeInstanceData::new(
×
NEW
61
        &args.app_name,
×
NEW
62
        &app_id,
×
NEW
63
        Some(hosting),
×
64
    ));
65
    let client_meta_information = ClientMetaInformation {
×
66
        app_name: args.app_name.clone(),
×
67
        instance_id: app_id.to_string(),
×
68
        connection_id: app_id.to_string(),
×
69
    };
×
70
    let instances_observed_for_app_context: Arc<RwLock<Vec<EdgeInstanceData>>> =
×
UNCOV
71
        Arc::new(RwLock::new(Vec::new()));
×
72
    let metrics_middleware =
×
73
        PrometheusAxumLayer::new(&args.app_name.clone(), &app_id.clone().to_string());
×
74

75
    let (app_state, background_tasks, shutdown_tasks) = match &args.mode {
×
76
        EdgeMode::Edge(edge_args) => {
×
77
            let http_client = new_reqwest_client(HttpClientArgs {
×
78
                skip_ssl_verification: edge_args.skip_ssl_verification,
×
79
                client_identity: edge_args.client_identity.clone(),
×
80
                upstream_certificate_file: edge_args.upstream_certificate_file.clone(),
×
81
                connect_timeout: Duration::seconds(edge_args.upstream_request_timeout),
×
82
                socket_timeout: Duration::seconds(edge_args.upstream_socket_timeout),
×
UNCOV
83
                keep_alive_timeout: Duration::seconds(edge_args.client_keepalive_timeout),
×
84
                client_meta_information: client_meta_information.clone(),
×
UNCOV
85
            })?;
×
86

87
            let auth_headers = AuthHeaders::from(&args);
×
88

89
            build_edge_state(
×
90
                args.clone(),
×
91
                edge_args,
×
92
                client_meta_information,
×
93
                edge_instance_data.clone(),
×
94
                instances_observed_for_app_context.clone(),
×
95
                auth_headers,
×
UNCOV
96
                http_client,
×
97
            )
×
98
            .await?
×
99
        }
100
        EdgeMode::Offline(offline_args) => {
×
UNCOV
101
            build_offline_app_state(args.clone(), offline_args.clone()).await?
×
102
        }
103
        _ => unreachable!(),
×
104
    };
105

UNCOV
106
    for task in background_tasks {
×
107
        tokio::spawn(task);
×
108
    }
×
109

110
    let api_router = Router::new()
×
111
        .nest("/client", unleash_edge_client_api::router())
×
112
        .merge(unleash_edge_frontend_api::router(args.disable_all_endpoint))
×
113
        .layer(
×
UNCOV
114
            ServiceBuilder::new()
×
UNCOV
115
                .layer(from_fn_with_state(
×
116
                    app_state.clone(),
×
117
                    middleware::validate_token::validate_token,
118
                ))
UNCOV
119
                .layer(from_fn_with_state(
×
120
                    app_state.clone(),
×
121
                    middleware::consumption::connection_consumption,
122
                ))
123
                .layer(from_fn(middleware::etag::etag_middleware)),
×
124
        );
125

126
    let top_router: Router = Router::new()
×
127
        .nest("/api", api_router)
×
128
        .nest("/edge", unleash_edge_edge_api::router())
×
129
        .nest(
×
130
            "/internal-backstage",
×
UNCOV
131
            Router::new()
×
132
                .route("/metrics", get(render_prometheus_metrics))
×
133
                .merge(unleash_edge_backstage::router(args.internal_backstage)),
×
134
        )
135
        .layer(
×
136
            ServiceBuilder::new()
×
137
                .layer(CompressionLayer::new())
×
138
                .layer(metrics_middleware)
×
UNCOV
139
                .layer(args.http.cors.middleware())
×
UNCOV
140
                .layer(from_fn_with_state(
×
141
                    app_state.clone(),
×
142
                    middleware::deny_list::deny_middleware,
143
                ))
UNCOV
144
                .layer(from_fn_with_state(
×
UNCOV
145
                    app_state.clone(),
×
146
                    middleware::allow_list::allow_middleware,
147
                )),
148
        )
149
        .with_state(app_state);
×
150
    let router_to_host = if args.http.base_path.len() > 1 {
×
UNCOV
151
        info!("Had a path different from root. Setting up a nested router");
×
152
        let path = if !args.http.base_path.starts_with("/") {
×
UNCOV
153
            format!("/{}", args.http.base_path)
×
154
        } else {
UNCOV
155
            args.http.base_path.clone()
×
156
        };
UNCOV
157
        Router::new().nest(&path, top_router)
×
158
    } else {
159
        top_router
×
160
    };
161

UNCOV
162
    Ok((router_to_host, shutdown_tasks))
×
UNCOV
163
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc