vdi_simple_gethdrs(const struct director *d, struct worker *wrk, struct busyobj *bo) { int i; CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); bo->vbc = VDI_GetFd(d, wrk, bo); if (bo->vbc == NULL) { VSLb(bo->vsl, SLT_FetchError, "no backend connection"); return (-1); } i = V1F_fetch_hdr(wrk, bo); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { AZ(bo->vbc); VSC_C_main->backend_retry++; bo->vbc = VDI_GetFd(d, wrk, bo); if (bo->vbc == NULL) { VSLb(bo->vsl, SLT_FetchError, "no backend connection"); return (-1); } i = V1F_fetch_hdr(wrk, bo); } if (i != 0) AZ(bo->vbc); else AN(bo->vbc); return (i); }
static enum fetch_step vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) { int i; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); xxxassert (wrk->handling == VCL_RET_FETCH); HTTP_Setup(bo->beresp, bo->ws, bo->vsl, HTTP_Beresp); if (!bo->do_pass) vbf_release_req(bo); /* XXX: retry ?? */ assert(bo->state == BOS_INVALID); i = V1F_fetch_hdr(wrk, bo, bo->req); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { VSC_C_main->backend_retry++; i = V1F_fetch_hdr(wrk, bo, bo->req); } if (bo->do_pass) vbf_release_req(bo); /* XXX : retry ?? */ AZ(bo->req); if (i) { AZ(bo->vbc); bo->err_code = 503; http_SetH(bo->beresp, HTTP_HDR_PROTO, "HTTP/1.1"); http_SetResp(bo->beresp, "HTTP/1.1", 503, "Backend fetch failed"); http_SetHeader(bo->beresp, "Content-Length: 0"); http_SetHeader(bo->beresp, "Connection: close"); } else { AN(bo->vbc); } /* * 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 * NB: Also sets other wrk variables */ bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); bo->err_code = http_GetStatus(bo->beresp); /* * What does RFC2616 think about TTL ? */ EXP_Clr(&bo->exp); bo->exp.entered = W_TIM_real(wrk); RFC2616_Ttl(bo); /* pass from vclrecv{} has negative TTL */ if (bo->fetch_objcore->objhead == NULL) bo->exp.ttl = -1.; AZ(bo->do_esi); VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (bo->do_esi) bo->do_stream = 0; if (wrk->handling == VCL_RET_DELIVER) return (F_STP_FETCH); if (wrk->handling == VCL_RET_RETRY) { assert(bo->state == BOS_INVALID); bo->retries++; if (bo->retries <= cache_param->max_retries) { VDI_CloseFd(&bo->vbc); return (F_STP_STARTFETCH); } // XXX: wrk->handling = VCL_RET_SYNTH; } return (F_STP_NOTYET); }
static enum fetch_step vbf_stp_fetchhdr(struct worker *wrk, struct busyobj *bo) { int i, do_ims; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); xxxassert (wrk->handling == VCL_RET_FETCH); HTTP_Setup(bo->beresp, bo->ws, bo->vsl, HTTP_Beresp); if (!bo->do_pass && bo->req != NULL) vbf_release_req(bo); /* XXX: retry ?? */ assert(bo->state <= BOS_REQ_DONE); i = V1F_fetch_hdr(wrk, bo, bo->req); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { VSC_C_main->backend_retry++; i = V1F_fetch_hdr(wrk, bo, bo->req); } if (bo->do_pass && bo->req != NULL) vbf_release_req(bo); /* XXX : retry ?? */ AZ(bo->req); if (i) { AZ(bo->vbc); make_it_503(bo); } else { AN(bo->vbc); } /* * 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 * NB: Also sets other wrk variables */ bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); if (i && bo->htc.body_status == BS_LENGTH) bo->htc.body_status = BS_NONE; bo->err_code = http_GetStatus(bo->beresp); /* * What does RFC2616 think about TTL ? */ EXP_Clr(&bo->exp); RFC2616_Ttl(bo); /* private objects have negative TTL */ if (bo->fetch_objcore->flags & OC_F_PRIVATE) bo->exp.ttl = -1.; AZ(bo->do_esi); if (bo->ims_obj != NULL && bo->beresp->status == 304) { bo->beresp->status = 200; http_PrintfHeader(bo->beresp, "Content-Length: %jd", (intmax_t)bo->ims_obj->len); do_ims = 1; } else do_ims = 0; VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (bo->do_esi) bo->do_stream = 0; if (bo->do_pass) bo->fetch_objcore->flags |= OC_F_PASS; if (wrk->handling == VCL_RET_DELIVER) return (do_ims ? F_STP_CONDFETCH : F_STP_FETCH); if (wrk->handling == VCL_RET_RETRY) { assert(bo->state == BOS_REQ_DONE); bo->retries++; if (bo->retries <= cache_param->max_retries) { VDI_CloseFd(&bo->vbc); return (F_STP_STARTFETCH); } // XXX: wrk->handling = VCL_RET_SYNTH; } INCOMPL(); }
static enum fetch_step vbf_stp_startfetch(struct worker *wrk, struct busyobj *bo) { int i, do_ims; double now; char time_str[VTIM_FORMAT_SIZE]; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AZ(bo->vbc); assert(bo->doclose == SC_NULL); AZ(bo->storage_hint); if (bo->do_pass) AN(bo->req); else AZ(bo->req); HTTP_Setup(bo->bereq, bo->ws, bo->vsl, SLT_BereqMethod); HTTP_Copy(bo->bereq, bo->bereq0); http_PrintfHeader(bo->bereq, "X-Varnish: %u", VXID(bo->vsl->wid)); VCL_backend_fetch_method(bo->vcl, wrk, NULL, bo, bo->bereq->ws); 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); i = V1F_fetch_hdr(wrk, bo, bo->req); /* * If we recycle a backend connection, there is a finite chance * that the backend closed it before we get a request to it. * Do a single retry in that case. */ if (i == 1) { VSLb_ts_busyobj(bo, "Beresp", W_TIM_real(wrk)); VSC_C_main->backend_retry++; i = V1F_fetch_hdr(wrk, bo, bo->req); } now = W_TIM_real(wrk); VSLb_ts_busyobj(bo, "Beresp", now); if (i) { AZ(bo->vbc); return (F_STP_ERROR); } AN(bo->vbc); 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. */ VTIM_format(now, time_str); http_PrintfHeader(bo->beresp, "Date: %s", time_str); } /* * 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 * NB: Also sets other wrk variables */ bo->htc.body_status = RFC2616_Body(bo, &wrk->stats); if (bo->htc.body_status == BS_ERROR) { AN (bo->vbc); VDI_CloseFd(&bo->vbc, &bo->acct); VSLb(bo->vsl, SLT_Error, "Body cannot be fetched"); 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); if (bo->ims_obj != NULL && bo->beresp->status == 304) { http_Merge(bo->ims_obj->http, bo->beresp, bo->ims_obj->changed_gzip); assert(bo->beresp->status == 200); do_ims = 1; } else do_ims = 0; VFP_Setup(bo->vfc); bo->vfc->bo = bo; bo->vfc->http = bo->beresp; bo->vfc->vsl = bo->vsl; VCL_backend_response_method(bo->vcl, wrk, NULL, bo, bo->beresp->ws); if (wrk->handling == VCL_RET_ABANDON) return (F_STP_FAIL); if (wrk->handling == VCL_RET_RETRY) { AN (bo->vbc); VDI_CloseFd(&bo->vbc, &bo->acct); bo->doclose = SC_NULL; bo->retries++; if (bo->retries <= cache_param->max_retries) return (F_STP_RETRY); VSLb(bo->vsl, SLT_VCL_Error, "Too many retries, delivering 503"); 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 (do_ims ? F_STP_CONDFETCH : F_STP_FETCH); }