From: Martin Kraemer Date: Tue, 8 Jan 2002 15:09:48 +0000 (+0000) Subject: The 416 "range not satisfiable" response would include a X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7c399bffeb20f802edbcc62badc69c1b6745db6f;p=thirdparty%2Fapache%2Fhttpd.git The 416 "range not satisfiable" response would include a Content-Length header set to the size of the resource, but no body was actually returned (r->header_only was set to 1). This appeared as a premature EOF to the client. Submitted by: Joe Orton Reviewed by: Martin Kraemer git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x@92767 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/CHANGES b/src/CHANGES index 3556cf12e91..0591c04482f 100644 --- a/src/CHANGES +++ b/src/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 1.3.23 + *) Fix incorrect "Content-Length" header in the 416 "range not + satisfiable" response. [Joe Orton ] + *) Add FileETag directive to control fields used when constructing an ETag for a file-based resource. Historically the inode, size, and mtimehave been used, but the inode factor broke diff --git a/src/main/http_protocol.c b/src/main/http_protocol.c index a9cee504a3b..dc21559273d 100644 --- a/src/main/http_protocol.c +++ b/src/main/http_protocol.c @@ -361,6 +361,7 @@ API_EXPORT(int) ap_set_byterange(request_rec *r) else { ap_table_setn(r->headers_out, "Content-Range", ap_psprintf(r->pool, "bytes */%ld", r->clength)); + ap_set_content_length(r, 0); r->boundary = NULL; r->range = range; r->header_only = 1; @@ -1040,16 +1041,43 @@ static int read_request_line(request_rec *r) r->protocol = ap_pstrdup(r->pool, "HTTP/1.0"); return 0; } - r->assbackwards = (ll[0] == '\0'); r->protocol = ap_pstrdup(r->pool, ll[0] ? ll : "HTTP/0.9"); - if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor) - && minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */ - r->proto_num = HTTP_VERSION(major, minor); - else - r->proto_num = HTTP_VERSION(1,0); + /* The following test tries to skip past the "HTTP/nn.mm" + * protocol string, collecting major=nn and minor=mm. + * ll is advanced past "HTTP/nn.mm" so that it can be checked + * for proper string termination (only valid chars: \r\n). + */ + if (memcmp(ll,"HTTP/",5) == 0 && isdigit(ll[5])) { + /* Read major protocol level: */ + major = strtol(&ll[5], &ll, 10); + if (errno != ERANGE && ll[0] == '/' && isdigit(ll[1])) { + + /* Read minor protocol level: */ + minor = strtol(&ll[1], &ll, 10); + + if (errno != ERANGE) { + if (minor < HTTP_VERSION(1,0)) /* don't allow HTTP/0.1000 */ + r->proto_num = HTTP_VERSION(major, minor); + else + r->proto_num = HTTP_VERSION(1,0); + } + } + } + /* If the request does not end after the "HTTP/x.y\r\n" (or after the + * URI in HTTP/0.9), then signal an error condition [400 Bad Request]. + */ + if (ll[strspn(ll," \r\n")] != '\0') { + ap_table_setn(r->notes, "error-notes", + "Request line not ending properly after \"HTTP/x.y\":" + "
\n", ap_escape_html(r->pool, r->protocol), "
"); + r->status = HTTP_BAD_REQUEST; + r->proto_num = HTTP_VERSION(1,0); + r->protocol = ap_pstrdup(r->pool, "HTTP/1.0"); + return 0; + } return 1; }