* 2 - chunk_size_start
* 3 - body_identity
* 4 - body_identity_eof
+ * 5 - invalid transfer-encoding for request
*/
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
const char* endp) {
if (parser->flags & F_SKIPBODY) {
return 0;
} else if (parser->flags & F_CHUNKED) {
- /* chunked encoding - ignore Content-Length header */
+ /* chunked encoding - ignore Content-Length header, prepare for a chunk */
return 2;
+ } else if (parser->flags & F_TRANSFER_ENCODING) {
+ if (parser->type == HTTP_REQUEST && (parser->flags & F_LENIENT) == 0) {
+ /* RFC 7230 3.3.3 */
+
+ /* If a Transfer-Encoding header field
+ * is present in a request and the chunked transfer coding is not
+ * the final encoding, the message body length cannot be determined
+ * reliably; the server MUST respond with the 400 (Bad Request)
+ * status code and then close the connection.
+ */
+ return 5;
+ } else {
+ /* RFC 7230 3.3.3 */
+
+ /* If a Transfer-Encoding header field is present in a response and
+ * the chunked transfer coding is not the final encoding, the
+ * message body length is determined by reading the connection until
+ * it is closed by the server.
+ */
+ return 4;
+ }
} else {
if (!(parser->flags & F_CONTENT_LENGTH)) {
if (!llhttp_message_needs_eof(parser)) {
int should_keep_alive;
should_keep_alive = llhttp_should_keep_alive(parser);
- parser->flags = 0;
parser->finish = HTTP_FINISH_SAFE;
+ /* Keep `F_LENIENT` flag between messages, but reset every other flag */
+ parser->flags &= F_LENIENT;
+
/* NOTE: this is ignored in loose parsing mode */
return should_keep_alive;
}
return 0;
}
+ /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
+ if ((parser->flags & F_TRANSFER_ENCODING) &&
+ (parser->flags & F_CHUNKED) == 0) {
+ return 1;
+ }
+
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
return 0;
}