예제 #1
0
void
http_SetHeader(struct http *to, const char *hdr)
{

    CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
    if (to->nhd >= to->shd) {
        VSC_C_main->losthdr++;
        VSLb(to->vsl, SLT_LostHeader, "%s", hdr);
        return;
    }
    http_SetH(to, to->nhd++, hdr);
}
예제 #2
0
void
http_SetHeader(struct worker *w, unsigned vsl_id, struct http *to,
    const char *hdr)
{

	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
	if (to->nhd >= to->shd) {
		VSC_C_main->losthdr++;
		WSL(w, SLT_LostHeader, vsl_id, "%s", hdr);
		return;
	}
	http_SetH(to, to->nhd++, hdr);
}
예제 #3
0
void
http_FilterReq(struct http *to, const struct http *fm, unsigned how)
{
	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
	CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);

	http_linkh(to, fm, HTTP_HDR_METHOD);
	http_linkh(to, fm, HTTP_HDR_URL);
	if (how == HTTPH_R_FETCH)
		http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
	else
		http_linkh(to, fm, HTTP_HDR_PROTO);
	http_filterfields(to, fm, how);
}
예제 #4
0
static void
vrt_do_string(const struct http *hp, int fld,
              const char *err, const char *p, va_list ap)
{
    const char *b;

    AN(hp);
    b = VRT_String(hp->ws, NULL, p, ap);
    if (b == NULL || *b == '\0') {
        VSLb(hp->vsl, SLT_LostHeader, "%s", err);
    } else {
        http_SetH(hp, fld, b);
    }
    va_end(ap);
}
예제 #5
0
static void
vrt_do_string(const struct http *hp, int fld,
    const char *err, const char *p, va_list ap)
{
	const char *b;

	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	b = VRT_String(hp->ws, NULL, p, ap);
	if (b == NULL || *b == '\0') {
		VSLb(hp->vsl, SLT_LostHeader, "%s", err);
		WS_MarkOverflow(hp->ws);
		return;
	}
	http_SetH(hp, fld, b);
}
예제 #6
0
void
http_FilterReq(const struct req *req, unsigned how)
{
    struct http *hp;

    hp = req->busyobj->bereq;
    CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

    http_linkh(hp, req->http, HTTP_HDR_METHOD);
    http_linkh(hp, req->http, HTTP_HDR_URL);
    if (how == HTTPH_R_FETCH)
        http_SetH(hp, HTTP_HDR_PROTO, "HTTP/1.1");
    else
        http_linkh(hp, req->http, HTTP_HDR_PROTO);
    http_filterfields(hp, req->http, how);
    http_PrintfHeader(hp, "X-Varnish: %u", req->vsl->wid & VSL_IDENTMASK);
}
예제 #7
0
void
http_SetStatus(struct http *to, uint16_t status)
{
	char buf[4];

	CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
	/*
	 * We allow people to use top digits for internal VCL
	 * signalling, but strip them from the ASCII version.
	 */
	to->status = status;
	status %= 1000;
	assert(status >= 100);
	bprintf(buf, "%03d", status);
	http_PutField(to, HTTP_HDR_STATUS, buf);
	http_SetH(to, HTTP_HDR_REASON, http_Status2Reason(status));
}
예제 #8
0
void
http_FilterHeader(const struct sess *sp, unsigned how)
{
	struct http *hp;

	hp = sp->wrk->bereq;
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	hp->logtag = HTTP_Tx;

	http_copyh(hp, sp->http, HTTP_HDR_REQ);
	http_copyh(hp, sp->http, HTTP_HDR_URL);
	if (how == HTTPH_R_FETCH)
		http_SetH(hp, HTTP_HDR_PROTO, "HTTP/1.1");
	else
		http_copyh(hp, sp->http, HTTP_HDR_PROTO);
	http_FilterFields(sp->wrk, sp->fd, hp, sp->http, how);
	http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid);
}
예제 #9
0
void
http_FilterReq(const struct sess *sp, unsigned how)
{
	struct http *hp;

	hp = sp->req->busyobj->bereq;
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	hp->logtag = HTTP_Tx;

	http_linkh(hp, sp->req->http, HTTP_HDR_REQ);
	http_linkh(hp, sp->req->http, HTTP_HDR_URL);
	if (how == HTTPH_R_FETCH)
		http_SetH(hp, HTTP_HDR_PROTO, "HTTP/1.1");
	else
		http_linkh(hp, sp->req->http, HTTP_HDR_PROTO);
	http_filterfields(hp, sp->req->http, how);
	http_PrintfHeader(hp, "X-Varnish: %u", sp->req->xid);
}
예제 #10
0
static void
vrt_do_string(VRT_CTX, struct http *hp, int fld,
    const char *err, const char *p, va_list ap)
{
	const char *b;

	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	b = VRT_String(hp->ws, NULL, p, ap);
	if (b == NULL) {
		VRT_fail(ctx, "Workspace overflow (%s)", err);
		WS_MarkOverflow(hp->ws);
		return;
	}
	if (*b == '\0') {
		VRT_fail(ctx, "Setting %s to empty string", err);
		return;
	}
	http_SetH(hp, fld, b);
}
예제 #11
0
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);
}
예제 #12
0
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);
}
예제 #13
0
void
http_ForceGet(const struct http *to)
{
	if (strcmp(http_GetReq(to), "GET"))
		http_SetH(to, HTTP_HDR_METHOD, "GET");
}