/* allocates and initializes an error response */
HttpReply *
errorBuildReply(ErrorState * err)
{
    HttpReply *rep = httpReplyCreate();
    const char *name = errorPageName(err->page_id);
    http_version_t version;
    /* no LMT for error pages; error pages expire immediately */
    httpBuildVersion(&version, 1, 0);
    if (strchr(name, ':')) {
	/* Redirection */
	char *quoted_url = rfc1738_escape_part(errorConvert('u', err));
	httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, 0, squid_curtime);
	httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url);
	httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s\n", err->http_status, "Access Denied");
    } else {
	MemBuf content = errorBuildContent(err);
	httpReplySetHeaders(rep, version, err->http_status, NULL, "text/html", content.size, 0, squid_curtime);
	/*
	 * include some information for downstream caches. Implicit
	 * replaceable content. This isn't quite sufficient. xerrno is not
	 * necessarily meaningful to another system, so we really should
	 * expand it. Additionally, we should identify ourselves. Someone
	 * might want to know. Someone _will_ want to know OTOH, the first
	 * X-CACHE-MISS entry should tell us who.
	 */
	httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d",
	    name, err->xerrno);
	httpBodySet(&rep->body, &content);
	/* do not memBufClean() the content, it was absorbed by httpBody */
    }
    return rep;
}
Example #2
0
static MemBuf
errorBuildContent(ErrorState * err)
{
    MemBuf content;
    const char *m;
    const char *p;
    const char *t;
    assert(err != NULL);
    assert(err->page_id > ERR_NONE && err->page_id < error_page_count);
    memBufDefInit(&content);
    m = error_text[err->page_id];
    assert(m);
    while ((p = strchr(m, '%'))) {
	memBufAppend(&content, m, p - m);	/* copy */
	t = errorConvert(*++p, err);	/* convert */
	memBufPrintf(&content, "%s", t);	/* copy */
	m = p + 1;		/* advance */
    }
    if (*m)
	memBufPrintf(&content, "%s", m);	/* copy tail */
    assert(content.size == strlen(content.buf));
    return content;
}