简体   繁体   中英

Content-Length Header in Http 2 for POST/PUT request with empty body required?

I am receiving a 411 length required error when sending HTTP2 POST requests without a body to an Azure API Management (but this is not a question about Azure). my request is:

curl --location --request POST "..." --header "Content-Type: application/json"  --verbose --http2

I'm getting the following logs from curl:

 ...
 Using HTTP2, server supports multi-use
 ...
 * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
 < HTTP/2 411
 < content-type: text/html; charset=us-ascii
 ...
 < content-length: 344
 < 
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 
 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
 <HTML><HEAD><TITLE>Length Required</TITLE>
 <META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
 <BODY><h2>Length Required</h2>
 <hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>

I thought this was not necessary for HTTP2, and tried reading what the HTTP2 RFC says about it, but found it confusing:

A request or response that includes a payload body can include a content-length header field.

But what about requests that don't have a body?

Who is correct here, the client who does not send the header, or the server who does not accept the request?

For HTTP/1.1 POST requests, client SHOULD send the Content-Length header, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 .

For HTTP/2, the Content-Length header is not mandated (see https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.6 ), since the protocol has the endStream flag to signal the end of the content.

However, server-side applications are typically written against a higher level HTTP semantic: they don't care whether the request came as HTTP/1.1 or HTTP/2, they just care if it was a POST with some header and some content that they want to process. See RFC 9110 for the definition of the high level HTTP semantic.

Given that HTTP/1.1 lasted for 20+ years and HTTP/2 is relatively new, server-side applications may still assume HTTP/1.1 and complain if some header that is present in HTTP/1.1 is missing because the request came as HTTP/2.

For example, HTTP/2 requests do not have the Host header anymore (instead, they have an :authority pseudo-header); however, HTTP/2 specifies that when translating HTTP/2 to HTTP/1.1 the Host header must be synthetically generated (see here ).

The same may happen to the Content-Length header: an old server-side application that assumes HTTP/1.1 expects the Content-Length header to be there, but when the request comes as HTTP/2 it may not have it because for HTTP/2 it is not strictly necessary. Here, "server-side application" may mean a reverse-proxy feature provided by a front-end server, or some Azure translation layer, or the final application reached by the request.

The most portable solution with curl would be for you to add Content-Length: 0 , or to specify an empty body with -d '' (so that curl adds the Content-Length: 0 header).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM