Beispiel #1
0
static time_t
httpReplyHdrExpirationTime_(const HttpReply * rep)
{
	if (rep->cache_control)
	{
		if (rep->date >= 0)
		{
			if (rep->cache_control->s_maxage >= 0)
				return rep->date + rep->cache_control->s_maxage;
			if (rep->cache_control->max_age >= 0)
				return rep->date + rep->cache_control->max_age;
		}
		else
		{
			if (rep->cache_control->s_maxage >= 0)
				return squid_curtime;
			if (rep->cache_control->max_age >= 0)
				return squid_curtime;
		}
	}
	if (Config.onoff.vary_ignore_expire &&
			httpHeaderHas(&rep->header, HDR_VARY))
	{
		const time_t d = httpHeaderGetTime(&rep->header, HDR_DATE);
		const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
		if (d == e)
			return -1;
	}
	if (httpHeaderHas(&rep->header, HDR_EXPIRES))
	{
		const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
		return e < 0 ? squid_curtime : e;
	}
	return -1;
}
/* returns true if connection should be "persistent" 
 * after processing this message */
int
httpMsgIsPersistent(http_version_t http_ver, const HttpHeader * hdr)
{
    if (httpHeaderHasConnDir(hdr, "close"))
	return 0;
#if WHEN_SQUID_IS_HTTP1_1
    if ((http_ver.major >= 1) && (http_ver.minor >= 1)) {
	/*
	 * for modern versions of HTTP: persistent unless there is
	 * a "Connection: close" header.
	 */
	return 1;
    } else {
#else
    {
#endif
	/*
	 * Persistent connections in Netscape 3.x are allegedly broken,
	 * return false if it is a browser connection.  If there is a
	 * VIA header, then we assume this is NOT a browser connection.
	 */
	const char *agent = httpHeaderGetStr(hdr, HDR_USER_AGENT);
	if (agent && !httpHeaderHas(hdr, HDR_VIA)) {
	    if (!strncasecmp(agent, "Mozilla/3.", 10))
		return 0;
	    if (!strncasecmp(agent, "Netscape/3.", 11))
		return 0;
	}
	/* for old versions of HTTP: persistent if has "keep-alive" */
	return httpHeaderHasConnDir(hdr, "keep-alive");
    }
}
int
refreshIsCachable(const StoreEntry * entry)
{
    /*
     * Don't look at the request to avoid no-cache and other nuisances.
     * the object should have a mem_obj so the URL will be found there.
     * 60 seconds delta, to avoid objects which expire almost
     * immediately, and which can't be refreshed.
     */
    int reason = refreshCheck(entry, NULL, Config.minimum_expiry_time);
    int can_revalidate = 0;
    refreshCounts[rcStore].total++;
    refreshCounts[rcStore].status[reason]++;
    if (reason < 200)
	/* Does not need refresh. This is certainly cachable */
	return 1;
    if (entry->lastmod > 0)
	can_revalidate = 1;
    if (entry->mem_obj && entry->mem_obj->reply) {
	if (httpHeaderHas(&entry->mem_obj->reply->header, HDR_ETAG))
	    can_revalidate = 1;
    }
    /* Last modified is needed to do a refresh */
    if (!can_revalidate)
	return 0;

    /* This seems to be refreshable. Cache it */
    return 1;
}
/*
 * return true if a given directive is found in at least one of
 * the "connection" header-fields note: if HDR_PROXY_CONNECTION is
 * present we ignore HDR_CONNECTION.
 */
int
httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive)
{
    String list;
    http_hdr_type ht;
    int res;
    /* what type of header do we have? */
    if (httpHeaderHas(hdr, HDR_PROXY_CONNECTION))
	ht = HDR_PROXY_CONNECTION;
    else if (httpHeaderHas(hdr, HDR_CONNECTION))
	ht = HDR_CONNECTION;
    else
	return 0;

    list = httpHeaderGetList(hdr, ht);
    res = strListIsMember(&list, directive, ',');
    stringClean(&list);
    return res;
}
Beispiel #5
0
static time_t
httpReplyHdrExpirationTime(const HttpReply * rep)
{
    /* The s-maxage and max-age directive takes priority over Expires */
    if (rep->cache_control) {
	if (rep->date >= 0) {
	    if (rep->cache_control->s_maxage >= 0)
		return rep->date + rep->cache_control->s_maxage;
	    if (rep->cache_control->max_age >= 0)
		return rep->date + rep->cache_control->max_age;
	} else {
	    /*
	     * Conservatively handle the case when we have a max-age
	     * header, but no Date for reference?
	     */
	    if (rep->cache_control->s_maxage >= 0)
		return squid_curtime;
	    if (rep->cache_control->max_age >= 0)
		return squid_curtime;
	}
    }
    if (Config.onoff.vary_ignore_expire &&
	httpHeaderHas(&rep->header, HDR_VARY)) {
	const time_t d = httpHeaderGetTime(&rep->header, HDR_DATE);
	const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
	if (d == e)
	    return -1;
    }
    if (httpHeaderHas(&rep->header, HDR_EXPIRES)) {
	const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
	/*
	 * HTTP/1.0 says that robust implementations should consider
	 * bad or malformed Expires header as equivalent to "expires
	 * immediately."
	 */
	return e < 0 ? squid_curtime : e;
    }
    return -1;
}
Beispiel #6
0
/*
 * The helper program receives queries on stdin, one
 * per line, and must return the result on on stdout
 */
static void
refreshCheckHandleReply(void *data, char *reply)
{
    refreshCheckState *state = data;
    refreshCheckState *next;
    int freshness = -1;
    char *log = NULL;
    MemBuf hdrs = MemBufNULL;


    debug(84, 2) ("refreshCheckHandleReply: reply=\"%s\"\n", reply);

    if (reply) {
	char *t = NULL;
	char *token = strwordtok(reply, &t);
	if (token && strcmp(token, "FRESH") == 0)
	    freshness = 0;
	else if (token && strcmp(token, "OK") == 0)
	    freshness = 0;

	while ((token = strwordtok(NULL, &t))) {
	    char *value = strchr(token, '=');
	    if (value) {
		*value++ = '\0';	/* terminate the token, and move up to the value */
		rfc1738_unescape(value);
		if (strcmp(token, "freshness") == 0)
		    freshness = atoi(value);
		else if (strcmp(token, "log") == 0)
		    log = value;
		else if (strncmp(token, "res{", 4) == 0) {
		    char *header, *t;
		    header = token + 4;
		    t = strrchr(header, '}');
		    if (!t)
			continue;
		    *t = '\0';
		    if (!hdrs.buf)
			memBufDefInit(&hdrs);
		    memBufPrintf(&hdrs, "%s: %s\r\n", header, value);
		}
	    }
	}
    }
    if (freshness >= 0) {
	if (hdrs.size) {
	    HttpReply *rep = httpReplyCreate();
	    httpHeaderParse(&rep->header, hdrs.buf, hdrs.buf + hdrs.size);
	    httpReplyUpdateOnNotModified(state->entry->mem_obj->reply, rep);
	    storeTimestampsSet(state->entry);
	    if (!httpHeaderHas(&rep->header, HDR_DATE)) {
		state->entry->timestamp = squid_curtime;
		state->entry->expires = squid_curtime + freshness;
	    } else if (freshness) {
		state->entry->expires = squid_curtime + freshness;
	    }
	    httpReplyDestroy(rep);
	    storeUpdate(state->entry, NULL);
	} else {
	    state->entry->timestamp = squid_curtime;
	    state->entry->expires = squid_curtime + freshness;
	}
    }
    if (hdrs.buf)
	memBufClean(&hdrs);
    dlinkDelete(&state->list, &state->def->queue);
    do {
	cbdataUnlock(state->def);
	state->def = NULL;

	if (state->callback && cbdataValid(state->callback_data))
	    state->callback(state->callback_data, freshness >= 0, log);
	cbdataUnlock(state->callback_data);
	state->callback_data = NULL;

	next = state->queue;
	cbdataFree(state);
	state = next;
    } while (state);
}