static enum fetch_step vbf_stp_mkbereq(struct worker *wrk, struct busyobj *bo) { const char *q; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC); assert(bo->fetch_objcore->boc->state == BOS_INVALID); AZ(bo->storage); HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod); http_FilterReq(bo->bereq0, bo->req->http, bo->do_pass ? HTTPH_R_PASS : HTTPH_R_FETCH); if (!bo->do_pass) { http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET"); http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1"); if (cache_param->http_gzip_support) http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip"); } else { AZ(bo->stale_oc); if (bo->bereq0->protover > 11) http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1"); } http_CopyHome(bo->bereq0); if (bo->stale_oc != NULL && ObjCheckFlag(bo->wrk, bo->stale_oc, OF_IMSCAND) && (bo->stale_oc->boc != NULL || ObjGetLen(wrk, bo->stale_oc) != 0)) { AZ(bo->stale_oc->flags & OC_F_PASS); q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_Last_Modified); if (q != NULL) http_PrintfHeader(bo->bereq0, "If-Modified-Since: %s", q); q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_ETag); if (q != NULL) http_PrintfHeader(bo->bereq0, "If-None-Match: %s", q); } HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod); bo->ws_bo = WS_Snapshot(bo->ws); HTTP_Copy(bo->bereq, bo->bereq0); if (bo->req->req_body_status == REQ_BODY_NONE) { bo->req = NULL; ObjSetState(bo->wrk, bo->fetch_objcore, BOS_REQ_DONE); } return (F_STP_STARTFETCH); }
static enum fetch_step vbf_stp_mkbereq(const struct worker *wrk, struct busyobj *bo) { const char *q; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC); assert(bo->state == BOS_INVALID); AZ(bo->storage_hint); HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod); http_FilterReq(bo->bereq0, bo->req->http, bo->do_pass ? HTTPH_R_PASS : HTTPH_R_FETCH); if (!bo->do_pass) { http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET"); http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1"); if (cache_param->http_gzip_support) http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip"); AN(bo->req); bo->req = NULL; http_CopyHome(bo->bereq0); } else AZ(bo->stale_oc); if (bo->stale_oc != NULL) { q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_Last_Modified); if (q != NULL) http_PrintfHeader(bo->bereq0, "If-Modified-Since: %s", q); q = HTTP_GetHdrPack(bo->wrk, bo->stale_oc, H_ETag); if (q != NULL) http_PrintfHeader(bo->bereq0, "If-None-Match: %s", q); } HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod); bo->ws_bo = WS_Snapshot(bo->ws); HTTP_Copy(bo->bereq, bo->bereq0); VBO_setstate(bo, BOS_REQ_DONE); return (F_STP_STARTFETCH); }
static enum fetch_step vbf_stp_mkbereq(const struct worker *wrk, struct busyobj *bo) { char *p; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); CHECK_OBJ_NOTNULL(bo->req, REQ_MAGIC); assert(bo->state == BOS_INVALID); AZ(bo->vbc); assert(bo->doclose == SC_NULL); AZ(bo->storage_hint); HTTP_Setup(bo->bereq0, bo->ws, bo->vsl, SLT_BereqMethod); http_FilterReq(bo->bereq0, bo->req->http, bo->do_pass ? HTTPH_R_PASS : HTTPH_R_FETCH); if (!bo->do_pass) { http_ForceField(bo->bereq0, HTTP_HDR_METHOD, "GET"); http_ForceField(bo->bereq0, HTTP_HDR_PROTO, "HTTP/1.1"); if (cache_param->http_gzip_support) http_ForceHeader(bo->bereq0, H_Accept_Encoding, "gzip"); AN(bo->req); bo->req = NULL; http_CopyHome(bo->bereq0); } if (bo->ims_obj != NULL && bo->ims_obj->http->status == 200) { if (http_GetHdr(bo->ims_obj->http, H_Last_Modified, &p)) { http_PrintfHeader(bo->bereq0, "If-Modified-Since: %s", p); } if (http_GetHdr(bo->ims_obj->http, H_ETag, &p)) { http_PrintfHeader(bo->bereq0, "If-None-Match: %s", p); } } VBO_setstate(bo, BOS_REQ_DONE); return (F_STP_STARTFETCH); }
static void ved_include(struct req *preq, const char *src, const char *host, struct ecx *ecx) { struct worker *wrk; struct req *req; enum req_fsm_nxt s; struct transport xp; CHECK_OBJ_NOTNULL(preq, REQ_MAGIC); CHECK_OBJ_NOTNULL(ecx, ECX_MAGIC); wrk = preq->wrk; if (preq->esi_level >= cache_param->max_esi_depth) return; req = Req_New(wrk, preq->sp); req->req_body_status = REQ_BODY_NONE; AZ(req->vsl->wid); req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER); VSLb(req->vsl, SLT_Begin, "req %u esi", VXID(preq->vsl->wid)); VSLb(preq->vsl, SLT_Link, "req %u esi", VXID(req->vsl->wid)); req->esi_level = preq->esi_level + 1; if (preq->esi_level == 0) assert(preq->top == preq); else CHECK_OBJ_NOTNULL(preq->top, REQ_MAGIC); req->top = preq->top; HTTP_Copy(req->http0, preq->http0); req->http0->ws = req->ws; req->http0->vsl = req->vsl; req->http0->logtag = SLT_ReqMethod; req->http0->conds = 0; http_SetH(req->http0, HTTP_HDR_URL, src); if (host != NULL && *host != '\0') { http_Unset(req->http0, H_Host); http_SetHeader(req->http0, host); } http_ForceField(req->http0, HTTP_HDR_METHOD, "GET"); http_ForceField(req->http0, HTTP_HDR_PROTO, "HTTP/1.1"); /* Don't allow conditionalss, we can't use a 304 */ http_Unset(req->http0, H_If_Modified_Since); http_Unset(req->http0, H_If_None_Match); /* Don't allow Range */ http_Unset(req->http0, H_Range); /* Set Accept-Encoding according to what we want */ http_Unset(req->http0, H_Accept_Encoding); if (ecx->isgzip) http_ForceHeader(req->http0, H_Accept_Encoding, "gzip"); /* Client content already taken care of */ http_Unset(req->http0, H_Content_Length); /* Reset request to status before we started messing with it */ HTTP_Copy(req->http, req->http0); req->vcl = preq->vcl; preq->vcl = NULL; req->wrk = preq->wrk; /* * XXX: We should decide if we should cache the director * XXX: or not (for session/backend coupling). Until then * XXX: make sure we don't trip up the check in vcl_recv. */ req->req_step = R_STP_RECV; req->t_req = preq->t_req; assert(isnan(req->t_first)); assert(isnan(req->t_prev)); INIT_OBJ(&xp, TRANSPORT_MAGIC); xp.deliver = VED_Deliver; req->transport = &xp; req->transport_priv = ecx; THR_SetRequest(req); VSLb_ts_req(req, "Start", W_TIM_real(wrk)); req->ws_req = WS_Snapshot(req->ws); while (1) { req->wrk = wrk; s = CNT_Request(wrk, req); if (s == REQ_FSM_DONE) break; DSL(DBG_WAITINGLIST, req->vsl->wid, "loop waiting for ESI (%d)", (int)s); assert(s == REQ_FSM_DISEMBARK); AZ(req->wrk); (void)usleep(10000); } VRTPRIV_dynamic_kill(req->sp->privs, (uintptr_t)req); CNT_AcctLogCharge(wrk->stats, req); VSL_End(req->vsl); preq->vcl = req->vcl; req->vcl = NULL; req->wrk = NULL; THR_SetRequest(preq); Req_Release(req); }
static enum req_fsm_nxt cnt_recv(struct worker *wrk, struct req *req) { unsigned recv_handling; struct SHA256Context sha256ctx; const char *xff; const char *ci, *cp; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); AN(req->vcl); AZ(req->objcore); AZ(req->err_code); AZ(isnan(req->t_first)); AZ(isnan(req->t_prev)); AZ(isnan(req->t_req)); ci = SES_Get_String_Attr(req->sp, SA_CLIENT_IP); cp = SES_Get_String_Attr(req->sp, SA_CLIENT_PORT); VSLb(req->vsl, SLT_ReqStart, "%s %s", ci, cp); http_VSL_log(req->http); if (req->restarts == 0) { /* * This really should be done earlier, but we want to capture * it in the VSL log. */ http_CollectHdr(req->http, H_X_Forwarded_For); if (http_GetHdr(req->http, H_X_Forwarded_For, &xff)) { http_Unset(req->http, H_X_Forwarded_For); http_PrintfHeader(req->http, "X-Forwarded-For: %s, %s", xff, ci); } else { http_PrintfHeader(req->http, "X-Forwarded-For: %s", ci); } } /* By default we use the first backend */ AZ(req->director_hint); req->director_hint = VCL_DefaultDirector(req->vcl); AN(req->director_hint); req->d_ttl = -1; req->disable_esi = 0; req->hash_always_miss = 0; req->hash_ignore_busy = 0; req->client_identity = NULL; http_CollectHdr(req->http, H_Cache_Control); VFP_Setup(req->htc->vfc); req->htc->vfc->http = req->http; req->htc->vfc->wrk = wrk; if (req->transport->req_body != NULL) { req->transport->req_body(req); if (req->req_body_status == REQ_BODY_FAIL) { req->doclose = SC_OVERLOAD; return (REQ_FSM_DONE); } } VCL_recv_method(req->vcl, wrk, req, NULL, NULL); /* Attempts to cache req.body may fail */ if (req->req_body_status == REQ_BODY_FAIL) { req->doclose = SC_RX_BODY; return (REQ_FSM_DONE); } recv_handling = wrk->handling; /* We wash the A-E header here for the sake of VRY */ if (cache_param->http_gzip_support && (recv_handling != VCL_RET_PIPE) && (recv_handling != VCL_RET_PASS)) { if (RFC2616_Req_Gzip(req->http)) { http_ForceHeader(req->http, H_Accept_Encoding, "gzip"); } else { http_Unset(req->http, H_Accept_Encoding); } } SHA256_Init(&sha256ctx); VCL_hash_method(req->vcl, wrk, req, NULL, &sha256ctx); assert(wrk->handling == VCL_RET_LOOKUP); SHA256_Final(req->digest, &sha256ctx); switch(recv_handling) { case VCL_RET_PURGE: req->req_step = R_STP_PURGE; return (REQ_FSM_MORE); case VCL_RET_HASH: req->req_step = R_STP_LOOKUP; return (REQ_FSM_MORE); case VCL_RET_PIPE: if (req->esi_level == 0) { req->req_step = R_STP_PIPE; return (REQ_FSM_MORE); } VSLb(req->vsl, SLT_VCL_Error, "vcl_recv{} returns pipe for ESI included object." " Doing pass."); req->req_step = R_STP_PASS; return (REQ_FSM_DONE); case VCL_RET_PASS: req->req_step = R_STP_PASS; return (REQ_FSM_MORE); case VCL_RET_SYNTH: req->req_step = R_STP_SYNTH; return (REQ_FSM_MORE); default: WRONG("Illegal return from vcl_recv{}"); } }
static enum req_fsm_nxt cnt_recv(struct worker *wrk, struct req *req) { unsigned recv_handling; struct SHA256Context sha256ctx; char *xff; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->vcl, VCL_CONF_MAGIC); AZ(req->objcore); AZ(req->obj); AZ(req->objcore); AZ(isnan(req->t_first)); AZ(isnan(req->t_prev)); AZ(isnan(req->t_req)); VSLb(req->vsl, SLT_ReqStart, "%s %s", req->sp->client_addr_str, req->sp->client_port_str); http_VSL_log(req->http); if (req->err_code) { req->req_step = R_STP_SYNTH; return (REQ_FSM_MORE); } /* By default we use the first backend */ AZ(req->director_hint); req->director_hint = req->vcl->director[0]; AN(req->director_hint); req->d_ttl = -1; req->disable_esi = 0; req->hash_always_miss = 0; req->hash_ignore_busy = 0; req->client_identity = NULL; if (req->restarts == 0) { if (http_GetHdr(req->http, H_X_Forwarded_For, &xff)) { http_Unset(req->http, H_X_Forwarded_For); http_PrintfHeader(req->http, "X-Forwarded-For: %s, %s", xff, req->sp->client_addr_str); } else { http_PrintfHeader(req->http, "X-Forwarded-For: %s", req->sp->client_addr_str); } } http_CollectHdr(req->http, H_Cache_Control); VCL_recv_method(req->vcl, wrk, req, NULL, req->http->ws); /* Attempts to cache req.body may fail */ if (req->req_body_status == REQ_BODY_FAIL) { return (REQ_FSM_DONE); } recv_handling = wrk->handling; /* We wash the A-E header here for the sake of VRY */ if (cache_param->http_gzip_support && (recv_handling != VCL_RET_PIPE) && (recv_handling != VCL_RET_PASS)) { if (RFC2616_Req_Gzip(req->http)) { http_ForceHeader(req->http, H_Accept_Encoding, "gzip"); } else { http_Unset(req->http, H_Accept_Encoding); } } req->sha256ctx = &sha256ctx; /* so HSH_AddString() can find it */ SHA256_Init(req->sha256ctx); VCL_hash_method(req->vcl, wrk, req, NULL, req->http->ws); assert(wrk->handling == VCL_RET_LOOKUP); SHA256_Final(req->digest, req->sha256ctx); req->sha256ctx = NULL; if (!strcmp(req->http->hd[HTTP_HDR_METHOD].b, "HEAD")) req->wantbody = 0; else req->wantbody = 1; switch(recv_handling) { case VCL_RET_PURGE: req->req_step = R_STP_PURGE; return (REQ_FSM_MORE); case VCL_RET_HASH: req->req_step = R_STP_LOOKUP; return (REQ_FSM_MORE); case VCL_RET_PIPE: if (req->esi_level == 0) { req->req_step = R_STP_PIPE; return (REQ_FSM_MORE); } VSLb(req->vsl, SLT_VCL_Error, "vcl_recv{} returns pipe for ESI included object." " Doing pass."); req->req_step = R_STP_PASS; return (REQ_FSM_DONE); case VCL_RET_PASS: req->req_step = R_STP_PASS; return (REQ_FSM_MORE); case VCL_RET_SYNTH: req->req_step = R_STP_SYNTH; return (REQ_FSM_MORE); default: WRONG("Illegal return from vcl_recv{}"); } }