Commit 165f191d authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

So one of those strange cornercases in HTTP/1

If we send the backend a HTTP/1.0 request, and it doesn't have a
Content-Length, it cannot use Chunked and must fall back to EOF.

However, the protocol field in the response tells us what version
backend *could* have used, not what it *does* use.

So we can get a response with HTTP/1.1 and EOF, following HTTP/1.0
semantics - because we asked for it.

Most sensible backends avoid this, either by buffering and creation
of a C-L or, smartly, returning "HTTP/1.0", even though that
is strictly speaking against the apocrphal texts.

Anyway, now we cope...

Fixes: 	#1810
parent e06d5dc0
......@@ -805,7 +805,8 @@ enum sess_close http_DoConnection(struct http *hp);
htc_complete_f HTTP1_Complete;
uint16_t HTTP1_DissectRequest(struct http_conn *, struct http *);
uint16_t HTTP1_DissectResponse(struct http_conn *, struct http *);
uint16_t HTTP1_DissectResponse(struct http_conn *, struct http *resp,
const struct http *req);
unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
#define HTTPH(a, b, c) extern char b[];
......
......@@ -193,7 +193,7 @@ V1F_FetchRespHdr(struct busyobj *bo)
hp = bo->beresp;
i = HTTP1_DissectResponse(htc, hp);
i = HTTP1_DissectResponse(htc, hp, bo->bereq);
bo->acct.beresp_hdrbytes += htc->rxbuf_e - htc->rxbuf_b;
if (i) {
VSLb(bo->vsl, SLT_FetchError, "http format error");
......
......@@ -321,15 +321,15 @@ http1_body_status(const struct http *hp, struct http_conn *htc)
/*--------------------------------------------------------------------*/
static void
http1_proto_ver(struct http *hp)
static int8_t
http1_proto_ver(const struct http *hp)
{
if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.0"))
hp->protover = 10;
return (10);
else if (!strcasecmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
hp->protover = 11;
return (11);
else
hp->protover = 0;
return (0);
}
/*--------------------------------------------------------------------*/
......@@ -347,7 +347,7 @@ HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
retval = http1_splitline(hp, htc, HTTP1_Req);
if (retval != 0)
return (retval);
http1_proto_ver(hp);
hp->protover = http1_proto_ver(hp);
if (hp->protover == 0)
return (400);
......@@ -391,22 +391,28 @@ HTTP1_DissectRequest(struct http_conn *htc, struct http *hp)
/*--------------------------------------------------------------------*/
uint16_t
HTTP1_DissectResponse(struct http_conn *htc, struct http *hp)
HTTP1_DissectResponse(struct http_conn *htc, struct http *hp,
const struct http *req)
{
uint16_t retval = 0;
const char *p;
int8_t rv;
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
CHECK_OBJ_NOTNULL(req, HTTP_MAGIC);
if (http1_splitline(hp, htc, HTTP1_Resp))
retval = 503;
if (retval == 0) {
http1_proto_ver(hp);
hp->protover = http1_proto_ver(hp);
if (hp->protover == 0)
retval = 503;
rv = http1_proto_ver(req);
if (hp->protover > rv)
hp->protover = rv;
}
if (retval == 0 && Tlen(hp->hd[HTTP_HDR_STATUS]) != 3)
......
varnishtest "POST HTTP/1.0 response"
server s1 {
non-fatal
rxreq
txresp -proto HTTP/1.1 -nolen -hdr "Connection: close"
send "Hello World\n"
delay .4
} -start
varnish v1 -vcl+backend {
sub vcl_backend_fetch {
set bereq.proto = "HTTP/1.0";
}
} -start
client c1 {
txreq -req POST -hdr "Content-Length: 0"
rxresp
expect resp.bodylen == 12
} -run
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment