programatik29 / axum-server

High level server designed to be used with axum framework.
MIT License
166 stars 54 forks source link

Connecting via HTTP (unsecure) to `tls-rustls`-enabled HTTP/2 server returns an obsolete HTTP/0.9 response #121

Open Andrew15-5 opened 3 weeks ago

Andrew15-5 commented 3 weeks ago

Here is a MWA:

use axum_server_dual_protocol::ServerExt; // (1)

fn main() {
    let app = axum::Router::new().route("/", axum::routing::get(|| async {}));
    tokio::runtime::Runtime::new().unwrap().block_on(async {
        let tls_config =
            axum_server::tls_rustls::RustlsConfig::from_pem_file("cert.pem", "key.pem")
                .await
                .unwrap();
        let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3000));
        println!("Listenning on {addr}");
        // axum_server_dual_protocol::bind_dual_protocol(addr, tls_config) // (1)
        //     .set_upgrade(true) // (1)
        axum_server::bind_rustls(addr, tls_config) // (2)
            // axum_server::bind(addr) // (3)
            .serve(app.into_make_service())
            .await
            .unwrap();
    });
}
[dependencies]
axum = { version = "0.7.5", features = ["http2"] }
tokio = { version = "1.38.0", features = ["full"] }
axum-server = { version = "0.6.0", features = ["tls-rustls"] }
axum-server-dual-protocol = "0.6.0"

I also created an SSL certificate and a private key with:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=localhost"

Here is what I get with curl -sSLD - --cacert cert.pem --http0.9 http://localhost:3000 | bat -Ap:

\u{15}\u{3}\u{3}␀\u{2}\u{2}2

And here is what I get with curl -sSLD - --cacert cert.pem --http0.9 https://localhost:3000 | bat -Ap:

HTTP/2·200·␍␊
content-length:·0␍␊
date:·Wed,·12·Jun·2024·16:09:02·GMT␍␊
␍␊

If instead of secure server (2) I use unsecure one (3) I get (HTTP):

HTTP/1.1·200·OK␍␊
content-length:·0␍␊
date:·Wed,·12·Jun·2024·16:14:18·GMT␍␊
␍␊

and (HTTPS):

curl: (35) error:0A00010B:SSL routines::wrong version number

For dual protocol version (1) I get HTTP/2 200 for HTTPS and HTTP/1.1 200 OK for HTTP when .set_upgrade(true) isn't used, and if it is used then HTTP/2 200 for HTTPS and HTTP/1.1 301 Moved Permanently + HTTP/2 200 for HTTP.

This is very closely related to #48, but I figured that this is a bug, rather than a feature request, because the server neither used HTTP/1.1 (OK) as a response nor sent an error response (HTTP/1.1 5xx). Since the first case means basically the same what #48 describes (IIUC), then the only other thing left is to send some error response (I don't know if this must be 5xx or some other one). This is also the easiest of the two, IIUC.

If neither can be implemented, then this behavior should be documented (HTTP/0.9 response).