Skip to content

HTTP/3: Requests to nginx server fails with grease #2976

@NamLe0609

Description

@NamLe0609

I currently have an nginx/1.28.1 reverse proxy running on my server.

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    server_name minio.s3.com;

    ssl_protocols TLSv1.2 TLSv1.3;
    http3 on;
    add_header Alt-Svc 'h3=":443"; ma=86400' always;

    ssl_certificate /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/privkey.pem;

    location / {
        # Points at random port
        proxy_pass http://localhost:1234;
    }
}

I make a get request to this using the reqwest client below (version 0.13.1 with http3 feature) and get an error:

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = reqwest::Client::builder()
        .tls_danger_accept_invalid_certs(true)
        .http3_prior_knowledge()
        .build()?;

    let res = client
        .get("https://server:443/")
        .version(http::Version::HTTP_3)
        .send()
        .await?;

    eprintln!("Response: {:?} {}", res.version(), res.status());
    eprintln!("Headers: {:#?}\n", res.headers());

    let body = res.text().await?;

    println!("{body}");

    Ok(())
}
$ cargo run
Error: reqwest::Error { kind: Request, url: "https://server:443/", 
source: reqwest::Error { kind: Request, source: RemoteTerminate { code: H3_INTERNAL_ERROR } } }

However, by turning grease off, the request works properly:

let client = reqwest::Client::builder()
    .tls_danger_accept_invalid_certs(true)
    .http3_prior_knowledge()
    .http3_send_grease(false) // Disable grease
    .build()?;
$ cargo run
Response: HTTP/3.0 502 Bad Gateway
Headers: {
    "server": "nginx/1.28.1",
    "date": "Sun, 01 Mar 2026 23:26:11 GMT",
    "content-type": "text/html",
    "content-length": "157",
    "alt-svc": "h3=\":443\"; ma=86400",
}

<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.28.1</center>
</body>
</html>

Not sure why this happens, but it would be nice to point this out in case people decide to test reqwest with an nginx server.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions