Skip to content
This repository was archived by the owner on Nov 6, 2022. It is now read-only.

Commit b47c44d

Browse files
koichikry
authored andcommitted
Fix response body is not read
With HTTP/1.1, if neither Content-Length nor Transfer-Encoding is present, section 4.4 of RFC 2616 suggests http-parser needs to read a response body until the connection is closed (except the response must not include a body) See also nodejs/node-v0.x-archive#2457. Fixes #72
1 parent 3cf68f9 commit b47c44d

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

http_parser.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,9 +1733,20 @@ http_should_keep_alive (http_parser *parser)
17331733
/* HTTP/1.1 */
17341734
if (parser->flags & F_CONNECTION_CLOSE) {
17351735
return 0;
1736-
} else {
1737-
return 1;
17381736
}
1737+
if (parser->type == HTTP_RESPONSE) {
1738+
/* See RFC 2616 section 4.4 */
1739+
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
1740+
parser->status_code == 204 || /* No Content */
1741+
parser->status_code == 304 || /* Not Modified */
1742+
parser->flags & F_SKIPBODY) { /* response to a HEAD request */
1743+
return 1;
1744+
}
1745+
if (!(parser->flags & F_CHUNKED) && parser->content_length == -1) {
1746+
return 0;
1747+
}
1748+
}
1749+
return 1;
17391750
} else {
17401751
/* HTTP/1.0 or earlier */
17411752
if (parser->flags & F_CONNECTION_KEEP_ALIVE) {

test.c

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,8 @@ const struct message responses[] =
780780
, {.name= "404 no headers no body"
781781
,.type= HTTP_RESPONSE
782782
,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
783-
,.should_keep_alive= TRUE
784-
,.message_complete_on_eof= FALSE
783+
,.should_keep_alive= FALSE
784+
,.message_complete_on_eof= TRUE
785785
,.http_major= 1
786786
,.http_minor= 1
787787
,.status_code= 404
@@ -795,8 +795,8 @@ const struct message responses[] =
795795
, {.name= "301 no response phrase"
796796
,.type= HTTP_RESPONSE
797797
,.raw= "HTTP/1.1 301\r\n\r\n"
798-
,.should_keep_alive = TRUE
799-
,.message_complete_on_eof= FALSE
798+
,.should_keep_alive = FALSE
799+
,.message_complete_on_eof= TRUE
800800
,.http_major= 1
801801
,.http_minor= 1
802802
,.status_code= 301
@@ -1057,8 +1057,46 @@ const struct message responses[] =
10571057
{}
10581058
,.body= ""
10591059
}
1060-
, {.name= NULL } /* sentinel */
10611060

1061+
#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 13
1062+
/* The client should wait for the server's EOF. That is, when neither
1063+
* content-length nor transfer-encoding is specified, the end of body
1064+
* is specified by the EOF.
1065+
*/
1066+
, {.name= "neither content-length nor transfer-encoding response"
1067+
,.type= HTTP_RESPONSE
1068+
,.raw= "HTTP/1.1 200 OK\r\n"
1069+
"Content-Type: text/plain\r\n"
1070+
"\r\n"
1071+
"hello world"
1072+
,.should_keep_alive= FALSE
1073+
,.message_complete_on_eof= TRUE
1074+
,.http_major= 1
1075+
,.http_minor= 1
1076+
,.status_code= 200
1077+
,.num_headers= 1
1078+
,.headers=
1079+
{ { "Content-Type", "text/plain" }
1080+
}
1081+
,.body= "hello world"
1082+
}
1083+
1084+
#define NO_HEADERS_NO_BODY_204 14
1085+
, {.name= "204 no headers no body"
1086+
,.type= HTTP_RESPONSE
1087+
,.raw= "HTTP/1.1 204 No Content\r\n\r\n"
1088+
,.should_keep_alive= TRUE
1089+
,.message_complete_on_eof= FALSE
1090+
,.http_major= 1
1091+
,.http_minor= 1
1092+
,.status_code= 204
1093+
,.num_headers= 0
1094+
,.headers= {}
1095+
,.body_size= 0
1096+
,.body= ""
1097+
}
1098+
1099+
, {.name= NULL } /* sentinel */
10621100
};
10631101

10641102
int
@@ -1888,7 +1926,7 @@ main (void)
18881926

18891927
printf("response scan 1/2 ");
18901928
test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
1891-
, &responses[NO_HEADERS_NO_BODY_404]
1929+
, &responses[NO_HEADERS_NO_BODY_204]
18921930
, &responses[NO_REASON_PHRASE]
18931931
);
18941932

0 commit comments

Comments
 (0)