]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
RFC-compliant object invalidation behaviour.
authorbenno@jeamland.net <>
Thu, 28 Aug 2008 05:12:17 +0000 (15:12 +1000)
committerbenno@jeamland.net <>
Thu, 28 Aug 2008 05:12:17 +0000 (15:12 +1000)
- Switch the default from not purging if the method is unknown to purging if
  the method is unknown.
- When purging URIs sourced from Location and Content-Location headers, make
  sure the URL is absolute before a) comparing it to see if hosts match and b)
  actually trying to find it in the store.

src/HttpRequestMethod.cc
src/Server.cc
src/protos.h
src/url.cc

index 8b05d813c5bb03e2ddd13b16e0f3b9c4fde4c1ac..5ac93230451df794cfacee029f7a1b3041afc3cb 100644 (file)
@@ -246,7 +246,7 @@ HttpRequestMethod::purgesOthers() const
         /* 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
index 935222c35a39ac2d119bfc94a2537cd96210bb10..3a2ecab9efcb9a897b1817b88cb96f60596e207f 100644 (file)
@@ -402,11 +402,20 @@ sameUrlHosts(const char *url1, const char *url2)
 
 // 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
@@ -425,8 +434,8 @@ ServerStateData::maybePurgeOthers()
    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
index 313358bace63e7b9723f4c55aedd902c66f19e33..71f9fadee129be587420613397d34aa54776cb61 100644 (file)
@@ -638,6 +638,7 @@ SQUIDCEXTERN protocol_t urlParseProtocol(const char *, const char *e = NULL);
 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);
index 869ec4559b234b515a3e805b26e79c61ba3dea65..8cdf775cdf36547ba1d1fca6ab3f514fc321aacf 100644 (file)
@@ -532,6 +532,70 @@ urlCanonicalClean(const HttpRequest * request)
     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: