Gateway example forwards requests with multiple `Content-Length` headers
Describe the bug
The gateway example forwards requests with multiple Content-Length headers. The HTTP RFCs say not to forward such messages.
From RFC 7230:
If a message is received without Transfer-Encoding and with either multiple Content-Length header fields having differing field-values or a single Content-Length header field having an invalid value, then the message framing is invalid and the recipient MUST treat it as an unrecoverable error. If this is a request message, the server MUST respond with a 400 (Bad Request) status code and then close the connection.
Thus, upon receipt of a request with multiple Content-Length headers, the gateway example should reject the request with a 400.
Pingora info
Please include the following information about your environment:
Pingora version: 648a6ad0554442be5f9c8d396a66843552156d1f Rust version: cargo 1.79.0 (ffa9cf99a 2024-06-03) Operating system version: Debian 13
Steps to reproduce
- Get a fresh Debian container:
docker run --rm -it debian:trixie-slim
- Install dependencies:
apt -y update && apt -y upgrade && apt -y install ncat clang git curl cmake g++ && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && . ~/.cargo/env
- Clone and build Pingora:
git clone 'https://github.com/cloudflare/pingora' && cd pingora && cargo build --example gateway
- Run the gateway:
./target/debug/examples/gateway &
- Send a control request, and observe that it works as expected:
(printf 'GET / HTTP/1.1\r\nContent-Length: 1\r\nHost: one.one.one.one\r\n\r\nZ'; sleep 1) | ncat localhost 6191
- Add an extra
Content-Lengthheader, and send it again:
(printf 'GET / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 0\r\nHost: one.one.one.one\r\n\r\nZ'; sleep 1) | ncat localhost 6191
Expected results
Pingora should respond 400.
Observed results
Pingora forwarded the request to one.one.one.one, which responds 400. This is clear because the response has a CF-RAY header, which Pingora wouldn't insert on its own.
More reference https://datatracker.ietf.org/doc/html/rfc9112#section-6.3