nginx protocol_error ai_generated partial

upstream sent HTTP/2.0 response while reading response header from upstream

ID: nginx/upstream-sent-http-2-0-response-while-reading-response-header-from-upstream

Also available as: JSON · Markdown · 中文
80%Fix Rate
85%Confidence
1Evidence
2024-06-25First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
nginx 1.18.0 active
nginx 1.20.0 active
nginx 1.22.0 active
nginx 1.24.0 active

Root Cause

Upstream server responded with HTTP/2 (HTTP/2.0) but nginx is configured to use HTTP/1.x for proxying, causing a protocol mismatch.

generic

中文

上游服务器以HTTP/2(HTTP/2.0)响应,但nginx配置为使用HTTP/1.x进行代理,导致协议不匹配。

Official Documentation

https://nginx.org/en/docs/http/ngx_http_v2_module.html

Workarounds

  1. 80% success Configure nginx to proxy using HTTP/2 by setting proxy_http_version 2.0; (requires nginx compiled with HTTP/2 support and ngx_http_v2_module): location / { proxy_http_version 2.0; proxy_pass https://upstream; # Note: HTTPS required for HTTP/2 }
    Configure nginx to proxy using HTTP/2 by setting proxy_http_version 2.0; (requires nginx compiled with HTTP/2 support and ngx_http_v2_module):
    
    location / {
        proxy_http_version 2.0;
        proxy_pass https://upstream;  # Note: HTTPS required for HTTP/2
    }
  2. 75% success If the upstream is an HTTP/2 server, configure it to also support HTTP/1.1. For example, in a Node.js server using http2 module: const http2 = require('http2'); const http = require('http'); const server = http2.createServer(); server.on('stream', (stream, headers) => { stream.respond({ ':status': 200 }); stream.end('OK'); }); server.listen(8080); Add an HTTP/1.1 listener on a different port if needed.
    If the upstream is an HTTP/2 server, configure it to also support HTTP/1.1. For example, in a Node.js server using http2 module:
    
    const http2 = require('http2');
    const http = require('http');
    
    const server = http2.createServer();
    server.on('stream', (stream, headers) => {
        stream.respond({ ':status': 200 });
        stream.end('OK');
    });
    server.listen(8080);
    
    Add an HTTP/1.1 listener on a different port if needed.
  3. 70% success Use a load balancer like HAProxy that can convert HTTP/2 to HTTP/1.1: frontend http-in bind *:80 default_backend servers backend servers server upstream1 10.0.0.1:8080 proto h2 HAProxy can terminate HTTP/2 and forward as HTTP/1.1 to nginx.
    Use a load balancer like HAProxy that can convert HTTP/2 to HTTP/1.1:
    
    frontend http-in
        bind *:80
        default_backend servers
    
    backend servers
        server upstream1 10.0.0.1:8080 proto h2
    
    HAProxy can terminate HTTP/2 and forward as HTTP/1.1 to nginx.

中文步骤

  1. Configure nginx to proxy using HTTP/2 by setting proxy_http_version 2.0; (requires nginx compiled with HTTP/2 support and ngx_http_v2_module):
    
    location / {
        proxy_http_version 2.0;
        proxy_pass https://upstream;  # Note: HTTPS required for HTTP/2
    }
  2. If the upstream is an HTTP/2 server, configure it to also support HTTP/1.1. For example, in a Node.js server using http2 module:
    
    const http2 = require('http2');
    const http = require('http');
    
    const server = http2.createServer();
    server.on('stream', (stream, headers) => {
        stream.respond({ ':status': 200 });
        stream.end('OK');
    });
    server.listen(8080);
    
    Add an HTTP/1.1 listener on a different port if needed.
  3. Use a load balancer like HAProxy that can convert HTTP/2 to HTTP/1.1:
    
    frontend http-in
        bind *:80
        default_backend servers
    
    backend servers
        server upstream1 10.0.0.1:8080 proto h2
    
    HAProxy can terminate HTTP/2 and forward as HTTP/1.1 to nginx.

Dead Ends

Common approaches that don't work:

  1. 90% fail

    If the upstream only supports HTTP/2, forcing HTTP/1.1 will not change the upstream's response; the upstream will still send HTTP/2 responses.

  2. 95% fail

    Buffer size does not affect protocol version negotiation.

  3. 85% fail

    These headers are for WebSocket upgrades, not HTTP version negotiation.