mb.clean();
}
+void
+HttpHeader::putWarning(const int code, const char *const text)
+{
+ char buf[512];
+ snprintf(buf, sizeof(buf), "%i %s \"%s\"", code, visible_appname_string, text);
+ putStr(HDR_WARNING, buf);
+}
+
/* add extension header (these fields are not parsed/analyzed/joined, etc.) */
void
HttpHeader::putExt(const char *name, const char *value)
void putContRange(const HttpHdrContRange * cr);
void putRange(const HttpHdrRange * range);
void putSc(HttpHdrSc *sc);
+ void putWarning(const int code, const char *const text); ///< add a Warning header
void putExt(const char *name, const char *value);
int getInt(http_hdr_type id) const;
int64_t getInt64(http_hdr_type id) const;
) {
http->logType = LOG_TCP_NEGATIVE_HIT;
sendMoreData(result);
- } else if (!Config.onoff.offline && refreshCheckHTTP(e, r) && !http->flags.internal) {
+ } else if (!http->flags.internal && refreshCheckHTTP(e, r)) {
debugs(88, 5, "clientCacheHit: in refreshCheck() block");
/*
* We hold a stale copy; it needs to be validated
}
}
+ // add Warnings required by RFC 2616 if serving a stale hit
+ if (http->request->flags.stale_if_hit && logTypeIsATcpHit(http->logType)) {
+ hdr->putWarning(110, "Response is stale");
+ if (http->request->flags.need_validation)
+ hdr->putWarning(111, "Revalidation failed");
+ }
+
/* Filter unproxyable authentication types */
if (http->logType != LOG_TCP_DENIED &&
return 1;
}
+/// whether reply is stale if it is a hit
+static bool
+refreshIsStaleIfHit(const int reason)
+{
+ switch (reason) {
+ case FRESH_MIN_RULE:
+ case FRESH_LMFACTOR_RULE:
+ case FRESH_EXPIRES:
+ return false;
+ default:
+ return true;
+ }
+}
+
/* refreshCheck... functions below are protocol-specific wrappers around
* refreshCheck() function above */
int reason = refreshCheck(entry, request, 0);
refreshCounts[rcHTTP].total++;
refreshCounts[rcHTTP].status[reason]++;
- return (reason < 200) ? 0 : 1;
+ request->flags.stale_if_hit = refreshIsStaleIfHit(reason);
+ return (Config.onoff.offline || reason < 200) ? 0 : 1;
}
int
struct request_flags {
- request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),chunked_reply(0),stream_error(0),destinationIPLookedUp_(0) {
+ request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),chunked_reply(0),stream_error(0),destinationIPLookedUp_(0) {
#if USE_HTTP_VIOLATIONS
nocache_hack = 0;
#endif
unsigned int redirected:1;
unsigned int need_validation:1;
unsigned int fail_on_validation_err:1; ///< whether we should fail if validation fails
+ unsigned int stale_if_hit:1; ///< reply is stale if it is a hit
#if USE_HTTP_VIOLATIONS
unsigned int nocache_hack:1; /* for changing/ignoring no-cache requests */
#endif