uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp) { uint16_t retval; const char *p; const char *b = NULL, *e; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); retval = http1_splitline(hp, htc, HTTP1_Req, cache_param->http_req_hdr_len); if (retval != 0) return (retval); hp->protover = http1_proto_ver(hp); if (hp->protover == 0) return (400); if (http_CountHdr(hp, H_Host) > 1) return (400); if (http_CountHdr(hp, H_Content_Length) > 1) return (400); /* RFC2616, section 5.2, point 1 */ if (!strncasecmp(hp->hd[HTTP_HDR_URL].b, "http://", 7)) b = hp->hd[HTTP_HDR_URL].b + 7; else if (FEATURE(FEATURE_HTTPS_SCHEME) && !strncasecmp(hp->hd[HTTP_HDR_URL].b, "https://", 8)) b = hp->hd[HTTP_HDR_URL].b + 8; if (b) { e = strchr(b, '/'); if (e) { http_Unset(hp, H_Host); http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b); hp->hd[HTTP_HDR_URL].b = e; } } htc->body_status = http1_body_status(hp, htc, 1); if (htc->body_status == BS_ERROR) return (400); p = http_GetMethod(hp); AN(p); if (htc->body_status == BS_EOF) { assert(hp->protover == 10); /* RFC1945 8.3 p32 and D.1.1 p58 */ if (!strcasecmp(p, "post") || !strcasecmp(p, "put")) return (400); htc->body_status = BS_NONE; } /* HEAD with a body is a hard error */ if (htc->body_status != BS_NONE && !strcasecmp(p, "head")) return (400); return (retval); }
uint16_t HTTP1_DissectRequest(struct http_conn *htc, struct http *hp) { uint16_t retval; const char *p; const char *b, *e; CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); retval = http1_splitline(hp, htc, HTTP1_Req); if (retval != 0) return (retval); hp->protover = http1_proto_ver(hp); if (hp->protover == 0) return (400); if (http_CountHdr(hp, H_Host) > 1) return (400); if (http_CountHdr(hp, H_Content_Length) > 1) return (400); /* RFC2616, section 5.2, point 1 */ if (!strncasecmp(hp->hd[HTTP_HDR_URL].b, "http://", 7)) { b = e = hp->hd[HTTP_HDR_URL].b + 7; while (*e != '/' && *e != '\0') e++; if (*e == '/') { http_Unset(hp, H_Host); http_PrintfHeader(hp, "Host: %.*s", (int)(e - b), b); hp->hd[HTTP_HDR_URL].b = e; } } htc->body_status = http1_body_status(hp, htc); if (htc->body_status == BS_ERROR) return (400); p = http_GetMethod(hp); AN(p); if (htc->body_status == BS_EOF) { assert(hp->protover == 10); /* RFC1945 8.3 p32 and D.1.1 p58 */ if (!strcasecmp(p, "post") || !strcasecmp(p, "put")) return (400); htc->body_status = BS_NONE; } /* HEAD with a body is a hard error */ if (htc->body_status != BS_NONE && !strcasecmp(p, "head")) return (400); return (retval); }
static enum fetch_step vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) { int i; double now; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AZ(bo->storage_hint); if (bo->do_pass) AN(bo->req); else AZ(bo->req); if (bo->retries > 0) http_Unset(bo->bereq, "\012X-Varnish:"); http_PrintfHeader(bo->bereq, "X-Varnish: %u", VXID(bo->vsl->wid)); VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, NULL); bo->uncacheable = bo->do_pass; if (wrk->handling == VCL_RET_ABANDON) return (F_STP_FAIL); assert (wrk->handling == VCL_RET_FETCH); HTTP_Setup(bo->beresp, bo->ws, bo->vsl, SLT_BerespMethod); assert(bo->state <= BOS_REQ_DONE); AZ(bo->htc); i = VDI_GetHdr(wrk, bo); now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Beresp", now); if (i) { assert(bo->director_state == DIR_S_NULL); return (F_STP_ERROR); } http_VSL_log(bo->beresp); if (!http_GetHdr(bo->beresp, H_Date, NULL)) { /* * RFC 2616 14.18 Date: The Date general-header field * represents the date and time at which the message was * originated, having the same semantics as orig-date in * RFC 822. ... A received message that does not have a * Date header field MUST be assigned one by the recipient * if the message will be cached by that recipient or * gatewayed via a protocol which requires a Date. * * If we didn't get a Date header, we assign one here. */ http_TimeHeader(bo->beresp, "Date: ", now); } /* * These two headers can be spread over multiple actual headers * and we rely on their content outside of VCL, so collect them * into one line here. */ http_CollectHdr(bo->beresp, H_Cache_Control); http_CollectHdr(bo->beresp, H_Vary); /* * Figure out how the fetch is supposed to happen, before the * headers are adultered by VCL */ if (!strcasecmp(http_GetMethod(bo->bereq), "head")) { /* * A HEAD request can never have a body in the reply, * no matter what the headers might say. * [RFC2516 4.3 p33] */ wrk->stats->fetch_head++; bo->htc->body_status = BS_NONE; } else if (http_GetStatus(bo->beresp) <= 199) { /* * 1xx responses never have a body. * [RFC2616 4.3 p33] * ... but we should never see them. */ wrk->stats->fetch_1xx++; bo->htc->body_status = BS_ERROR; } else if (http_IsStatus(bo->beresp, 204)) { /* * 204 is "No Content", obviously don't expect a body. * [RFC7230 3.3.1 p28 and 3.3.2 p30] */ wrk->stats->fetch_204++; if (http_GetHdr(bo->beresp, H_Content_Length, NULL) || http_GetHdr(bo->beresp, H_Transfer_Encoding, NULL)) bo->htc->body_status = BS_ERROR; else bo->htc->body_status = BS_NONE; } else if (http_IsStatus(bo->beresp, 304)) { /* * 304 is "Not Modified" it has no body. * [RFC2616 10.3.5 p63] */ wrk->stats->fetch_304++; bo->htc->body_status = BS_NONE; } else if (bo->htc->body_status == BS_CHUNKED) { wrk->stats->fetch_chunked++; } else if (bo->htc->body_status == BS_LENGTH) { assert(bo->htc->content_length > 0); wrk->stats->fetch_length++; } else if (bo->htc->body_status == BS_EOF) { wrk->stats->fetch_eof++; } else if (bo->htc->body_status == BS_ERROR) { wrk->stats->fetch_bad++; } else if (bo->htc->body_status == BS_NONE) { wrk->stats->fetch_none++; } else { WRONG("wrong bodystatus"); } if (bo->htc->body_status == BS_ERROR) { bo->htc->doclose = SC_RX_BODY; VDI_Finish(bo->wrk, bo); VSLb(bo->vsl, SLT_Error, "Body cannot be fetched"); assert(bo->director_state == DIR_S_NULL); return (F_STP_ERROR); } /* * What does RFC2616 think about TTL ? */ EXP_Clr(&bo->fetch_objcore->exp); RFC2616_Ttl(bo, now); /* private objects have negative TTL */ if (bo->fetch_objcore->flags & OC_F_PRIVATE) bo->fetch_objcore->exp.ttl = -1.; AZ(bo->do_esi); AZ(bo->was_304); if (http_IsStatus(bo->beresp, 304)) { if (bo->stale_oc != NULL && ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND)) { if (ObjCheckFlag(bo->wrk, bo->stale_oc, OF_CHGGZIP)) { /* * If we changed the gzip status of the object * the stored Content_Encoding controls we * must weaken any new ETag we get. */ http_Unset(bo->beresp, H_Content_Encoding); RFC2616_Weaken_Etag(bo->beresp); } http_Unset(bo->beresp, H_Content_Length); HTTP_Merge(bo->wrk, bo->stale_oc, bo->beresp); assert(http_IsStatus(bo->beresp, 200)); bo->was_304 = 1; } else if (!bo->do_pass) { /* * Backend sent unallowed 304 */ VSLb(bo->vsl, SLT_Error, "304 response but not conditional fetch"); bo->htc->doclose = SC_RX_BAD; VDI_Finish(bo->wrk, bo); return (F_STP_FAIL); } } bo->vfc->bo = bo; bo->vfc->oc = bo->fetch_objcore; bo->vfc->wrk = bo->wrk; bo->vfc->http = bo->beresp; bo->vfc->esi_req = bo->bereq; VCL_backend_response_method(bo->vcl, wrk, NULL, bo, NULL); if (wrk->handling == VCL_RET_ABANDON) { bo->htc->doclose = SC_RESP_CLOSE; VDI_Finish(bo->wrk, bo); return (F_STP_FAIL); } if (wrk->handling == VCL_RET_RETRY) { if (bo->htc->body_status != BS_NONE) bo->htc->doclose = SC_RESP_CLOSE; if (bo->director_state != DIR_S_NULL) VDI_Finish(bo->wrk, bo); if (bo->retries++ < cache_param->max_retries) return (F_STP_RETRY); VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, delivering 503"); assert(bo->director_state == DIR_S_NULL); return (F_STP_ERROR); } assert(bo->state == BOS_REQ_DONE); if (bo->do_esi) bo->do_stream = 0; if (bo->do_pass || bo->uncacheable) bo->fetch_objcore->flags |= OC_F_PASS; assert(wrk->handling == VCL_RET_DELIVER); return (bo->was_304 ? F_STP_CONDFETCH : F_STP_FETCH); }