/* all others */
case METHOD_OTHER:
default:
- return false; // be conservative: we do not know some methods specs
+ return true; // RFC says to purge if we don't know the method
}
return false; // not reached
// purges entries that match the value of a given HTTP [response] header
static void
-purgeEntriesByHeader(const char *reqUrl, HttpMsg *rep, http_hdr_type hdr)
-{
- if (const char *url = rep->header.getStr(hdr))
- if (sameUrlHosts(reqUrl, url)) // prevent purging DoS, per RFC 2616
+purgeEntriesByHeader(const HttpRequest *req, const char *reqUrl, HttpMsg *rep, http_hdr_type hdr)
+{
+ if (const char *url = rep->header.getStr(hdr)) {
+ const char *absUrl = urlAbsolute(req, url);
+ if (absUrl != NULL) {
+ url = absUrl;
+ }
+ if (sameUrlHosts(reqUrl, url)) { // prevent purging DoS, per RFC 2616
purgeEntriesByUrl(url);
+ }
+ if (absUrl != NULL) {
+ xfree((void *)absUrl);
+ }
+ }
}
// some HTTP methods should purge matching cache entries
const char *reqUrl = urlCanonical(request);
debugs(88, 5, "maybe purging due to " << RequestMethodStr(request->method) << ' ' << reqUrl);
purgeEntriesByUrl(reqUrl);
- purgeEntriesByHeader(reqUrl, theFinalReply, HDR_LOCATION);
- purgeEntriesByHeader(reqUrl, theFinalReply, HDR_CONTENT_LOCATION);
+ purgeEntriesByHeader(request, reqUrl, theFinalReply, HDR_LOCATION);
+ purgeEntriesByHeader(request, reqUrl, theFinalReply, HDR_CONTENT_LOCATION);
}
// called (usually by kids) when we have final (possibly adapted) reply headers
SQUIDCEXTERN void urlInitialize(void);
SQUIDCEXTERN HttpRequest *urlParse(const HttpRequestMethod&, char *, HttpRequest *request = NULL);
SQUIDCEXTERN const char *urlCanonical(HttpRequest *);
+SQUIDCEXTERN const char *urlAbsolute(const HttpRequest *, const char *);
SQUIDCEXTERN char *urlRInternal(const char *host, u_short port, const char *dir, const char *name);
SQUIDCEXTERN char *urlInternal(const char *dir, const char *name);
SQUIDCEXTERN int matchDomainName(const char *host, const char *domain);
return buf;
}
+const char *
+urlAbsolute(const HttpRequest * req, const char *relUrl)
+{
+ LOCAL_ARRAY(char, portbuf, 32);
+ LOCAL_ARRAY(char, urlbuf, MAX_URL);
+ char *path, *last_slash;
+
+ if (relUrl == NULL) {
+ return (NULL);
+ }
+ if (req->method.id() == METHOD_CONNECT) {
+ return (NULL);
+ }
+ if (strchr(relUrl, ':') != NULL) {
+ return (NULL);
+ }
+ if (req->protocol == PROTO_URN) {
+ snprintf(urlbuf, MAX_URL, "urn:%s", req->urlpath.buf());
+ } else {
+ portbuf[0] = '\0';
+ if (req->port != urlDefaultPort(req->protocol)) {
+ snprintf(portbuf, 32, ":%d", req->port);
+ }
+ if (relUrl[0] == '/') {
+ snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s",
+ ProtocolStr[req->protocol],
+ req->login,
+ *req->login ? "@" : null_string,
+ req->GetHost(),
+ portbuf,
+ relUrl
+ );
+ } else {
+ path = xstrdup(req->urlpath.buf());
+ last_slash = strrchr(path, '/');
+ if (last_slash == NULL) {
+ snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s/%s",
+ ProtocolStr[req->protocol],
+ req->login,
+ *req->login ? "@" : null_string,
+ req->GetHost(),
+ portbuf,
+ relUrl
+ );
+ } else {
+ last_slash++;
+ *last_slash = '\0';
+ snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s%s%s",
+ ProtocolStr[req->protocol],
+ req->login,
+ *req->login ? "@" : null_string,
+ req->GetHost(),
+ portbuf,
+ path,
+ relUrl
+ );
+ }
+ xfree(path);
+ }
+ }
+
+ return (xstrdup(urlbuf));
+}
+
/*
* matchDomainName() compares a hostname with a domainname according
* to the following rules: