Crate axum_strangler

source ·
Expand description

Axum Strangler

A tower_service::Service for use in the axum web framework to apply the Strangler Fig pattern. This makes “strangling” a bit easier, as everything that is handled by the “strangler” will automatically no longer be forwarded to the “stranglee” or “strangled application” (a.k.a. the old application).

Example

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let strangler = axum_strangler::Strangler::new(
        axum::http::uri::Authority::from_static("127.0.0.1:3333"),
    );
    let router = axum::Router::new().fallback_service(strangler);
    axum::Server::bind(&"127.0.0.1:0".parse()?)
        .serve(router.into_make_service())
        .await?;
    Ok(())
}

Caveats

Note that when registering a route with axum, all requests will be handled by it, even if you don’t register anything for the specific method. This means that in the following snippet, requests for /new with the method POST, PUT, DELETE, OPTIONS, HEAD, PATCH, or TRACE will no longer be forwarded to the strangled application:

async fn handler() {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let strangler = axum_strangler::Strangler::new(
        axum::http::uri::Authority::from_static("127.0.0.1:3333"),
    );
    let router = axum::Router::new()
        .route(
            "/test",
             axum::routing::get(handler)
        )
        .fallback_service(strangler);
    axum::Server::bind(&"127.0.0.1:0".parse()?)
        .serve(router.into_make_service())
        .await?;
    Ok(())
}

If you only want to implement a single method and still forward the rest, you can do so by adding the strangler as the fallback for that specific MethodRouter:

async fn handler() {}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let strangler = axum_strangler::Strangler::new(
        axum::http::uri::Authority::from_static("127.0.0.1:3333"),
    );
    let router = axum::Router::new()
        .route(
            "/test",
            axum::routing::get(handler)
                .fallback_service(strangler.clone())
        )
        .fallback_service(strangler);
    axum::Server::bind(&"127.0.0.1:0".parse()?)
        .serve(router.into_make_service())
        .await?;
    Ok(())
}

Websocket support

If you enable the feature websocket (and possibly one of the supporting tls ones: websocket-native-tls, websocket-rustls-tls-native-roots, websocket-rustls-tls-webpki-roots), a websocket will be set up, and each websocket message will be relayed.

Tracing propagation

Enabling the tracing-opentelemetry-text-map-propagation feature, will cause traceparent header to be set on requests that get forwarded, based on the current tracing (& tracing-opentelemetry) context.

Note that this requires the opentelemetry TextMapPropagator to be installed.

Structs

Forwards all requests to another application. Can be used in a lot of places, but the most common one would be as a .fallback on an axum Router.

Enums