代码之家  ›  专栏  ›  技术社区  ›  Istvan

如何使用Axum/Tower压缩HTML内容?

  •  1
  • Istvan  · 技术社区  · 2 年前

    我正在尝试用Axum0.7和lambda_http0.9创建一个非常简单的API

    [package]
    name = "api"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    axum = "0.7"
    chrono = { version = "0.4" }
    cookie = { version = "0.18" }
    lambda_http = { version = "0.9" }
    serde = "1.0"
    serde_json = "1.0"
    askama = { version = "0.12.1" }
    tokio = { version = "1.35", features = ["macros"] }
    tower-http = { version = "0.5", features = ["compression-full", "cors"] }
    tracing = { version = "0.1", features = ["log"] }
    tracing-subscriber = { version = "0.3", default-features = false, features = [
        "fmt",
    ] }
    
    use axum::{
        http::{
            header::{ACCEPT, ACCEPT_ENCODING, AUTHORIZATION},
            Method,
        },
        routing::{get, post},
        Router,
    };
    use lambda_http::{run, Error};
    use tower_http::{compression::CompressionLayer, cors::CorsLayer};
    
    
    pub async fn get_index(request: Request) -> (StatusCode, Html<String>) {
        info!("-> {}", request.uri());
        info!("<- get_index");
        (StatusCode::OK, Html("<h1>/</h1>".to_string()))
    }
    
    
    #[tokio::main]
    async fn main() -> Result<(), Error> {
        let comression_layer: CompressionLayer = CompressionLayer::new()
            .br(true)
            .deflate(true)
            .gzip(true)
            .zstd(true);
    
        let app: Router = Router::new()
            .route("/", get(get_index))
            .layer(comression_layer)
            .fallback(not_found);
    
    
    

    当我在本地测试服务(使用cargo lambda)时,我得到以下结果:

    ❯ curl -H "Accept-Encoding: gzip, deflate, br" -i http://127.0.0.1:9000/
    HTTP/1.1 200 OK
    content-type: text/html; charset=utf-8
    content-length: 10
    access-control-allow-credentials: true
    vary: origin
    vary: access-control-request-method
    vary: access-control-request-headers
    date: Sun, 24 Dec 2023 21:17:29 GMT
    
    <h1>/</h1>⏎
    

    我是遗漏了一些琐碎的东西,还是API应该返回压缩内容?

    1 回复  |  直到 2 年前
        1
  •  2
  •   drewtato    2 年前

    我看了医生 CompressionLayer -> CompressionLayer::compress_when -> Compression::compress_when -> DefaultPredicate :

    这将压缩响应,除非:

    • ...
    • 响应小于32字节。

    你的似乎是11个字节。您可以通过使用 closure or function 作为谓词,它应该看起来像这样:

    let comression_layer: CompressionLayer = CompressionLayer::new()
        .br(true)
        .deflate(true)
        .gzip(true)
        .zstd(true)
        .compress_when(|_, _, _, _| true);
    

    或者你可以发送一个更大的回复。


    HTTP side ,允许服务器使用 identity 编码(无压缩),只要它没有被明确禁止。因此,您可以尝试使用curl命令来要求压缩:

    curl -H "Accept-Encoding: gzip, deflate, br, identity;q=0" -i http://127.0.0.1:9000/