static enum fetch_step vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo) { CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AZ(vbf_beresp2obj(bo)); if (ObjHasAttr(bo->wrk, bo->stale_oc, OA_ESIDATA)) AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_ESIDATA)); AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_FLAGS)); AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_GZIPBITS)); if (bo->do_stream) { ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM); HSH_Unbusy(wrk, bo->fetch_objcore); ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM); } if (ObjIterate(wrk, bo->stale_oc, bo, vbf_objiterator, 0)) (void)VFP_Error(bo->vfc, "Template object failed"); if (bo->stale_oc->flags & OC_F_FAILED) (void)VFP_Error(bo->vfc, "Template object failed"); if (bo->vfc->failed) { VDI_Finish(bo->wrk, bo); wrk->stats->fetch_failed++; return (F_STP_FAIL); } return (F_STP_FETCHEND); }
static enum fetch_step vbf_stp_condfetch(struct worker *wrk, struct busyobj *bo) { CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC); AZ(vbf_beresp2obj(bo)); if (ObjHasAttr(bo->wrk, bo->stale_oc, OA_ESIDATA)) AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_ESIDATA)); AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_FLAGS)); AZ(ObjCopyAttr(bo->wrk, bo->fetch_objcore, bo->stale_oc, OA_GZIPBITS)); if (bo->do_stream) { ObjSetState(wrk, bo->fetch_objcore, BOS_PREP_STREAM); HSH_Unbusy(wrk, bo->fetch_objcore); ObjSetState(wrk, bo->fetch_objcore, BOS_STREAM); } if (ObjIterate(wrk, bo->stale_oc, bo, vbf_objiterator, 0)) (void)VFP_Error(bo->vfc, "Template object failed"); if (bo->stale_oc->flags & OC_F_FAILED) (void)VFP_Error(bo->vfc, "Template object failed"); if (bo->vfc->failed) { VDI_Finish(bo->wrk, bo); return (F_STP_FAIL); } AZ(ObjSetU64(wrk, bo->fetch_objcore, OA_LEN, bo->fetch_objcore->boc->len_so_far)); if (!bo->do_stream) HSH_Unbusy(wrk, bo->fetch_objcore); HSH_Kill(bo->stale_oc); /* Recycle the backend connection before setting BOS_FINISHED to give predictable backend reuse behavior for varnishtest */ VDI_Finish(bo->wrk, bo); ObjSetState(wrk, bo->fetch_objcore, BOS_FINISHED); VSLb_ts_busyobj(bo, "BerespBody", W_TIM_real(wrk)); return (F_STP_DONE); }
static enum req_fsm_nxt cnt_transmit(struct worker *wrk, struct req *req) { struct boc *boc; const char *r; uint16_t status; int sendbody; intmax_t clval; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(req, REQ_MAGIC); CHECK_OBJ_NOTNULL(req->transport, TRANSPORT_MAGIC); /* Grab a ref to the bo if there is one */ boc = HSH_RefBoc(req->objcore); clval = http_GetContentLength(req->resp); if (boc != NULL) req->resp_len = clval; else req->resp_len = ObjGetLen(req->wrk, req->objcore); req->res_mode = 0; /* RFC 7230, 3.3.3 */ status = http_GetStatus(req->resp); if (!strcmp(req->http0->hd[HTTP_HDR_METHOD].b, "HEAD")) { if (req->objcore->flags & OC_F_PASS) sendbody = -1; else sendbody = 0; } else if (status < 200 || status == 204 || status == 304) { req->resp_len = -1; sendbody = 0; } else sendbody = 1; if (sendbody >= 0) { if (!req->disable_esi && req->resp_len != 0 && ObjHasAttr(wrk, req->objcore, OA_ESIDATA)) VDP_push(req, VDP_ESI, NULL, 0, "ESI"); if (cache_param->http_gzip_support && ObjCheckFlag(req->wrk, req->objcore, OF_GZIPED) && !RFC2616_Req_Gzip(req->http)) VDP_push(req, VDP_gunzip, NULL, 1, "GUZ"); if (cache_param->http_range_support && http_IsStatus(req->resp, 200)) { http_SetHeader(req->resp, "Accept-Ranges: bytes"); if (sendbody && http_GetHdr(req->http, H_Range, &r)) VRG_dorange(req, r); } } if (sendbody < 0) { /* Don't touch pass+HEAD C-L */ sendbody = 0; } else if (clval >= 0 && clval == req->resp_len) { /* Reuse C-L header */ } else { http_Unset(req->resp, H_Content_Length); if (req->resp_len >= 0 && sendbody) http_PrintfHeader(req->resp, "Content-Length: %jd", req->resp_len); } req->transport->deliver(req, boc, sendbody); VSLb_ts_req(req, "Resp", W_TIM_real(wrk)); if (req->objcore->flags & (OC_F_PRIVATE | OC_F_PASS)) { if (boc != NULL) { HSH_Abandon(req->objcore); ObjWaitState(req->objcore, BOS_FINISHED); } ObjSlim(wrk, req->objcore); } if (boc != NULL) HSH_DerefBoc(wrk, req->objcore); (void)HSH_DerefObjCore(wrk, &req->objcore); http_Teardown(req->resp); return (REQ_FSM_DONE); }