Looks like a possible RFC 2616 MUST violation. mod_cache does not ignore extension Cache-control directives. For example, when a directive includes something that looks like a standard directive (but is not), mod_cache honors the (non-existent) standard directive. See attached trace(s) for details and ways to reproduce the violation mentioned above. Note that the test cases check that a valid standard directive is honored first. The extension directive is tested in "step 2". Test case IDs in the trace link to human-oriented test case description and RFC quotes, if available.
Created attachment 15298 [details] max-age in the extension name this trace has max-age directive inside an blah=value extension directive
Created attachment 15299 [details] max-age in the extension value this trace has max-age directive inside the value of the blah=value extension directive
I believe this issue is still present in 2.3/trunk.
Confirming this in trunk again. First request to cache the url . |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 11:12:53 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Content-length: 5 Content-type: text/plain Last-modified: Tue, 26 Aug 2008 11:12:33 GMT Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Connection: close abcd This request used the cached URL |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 11:12:53 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Last-Modified: Tue, 26 Aug 2008 11:12:17 GMT Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Age: 1 Connection: close Content-Type: text/plain abcd This one didn't (Note the quoted "name"=value ) |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: " max-age=0 "=new\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 11:13:02 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Last-Modified: Tue, 26 Aug 2008 11:12:24 GMT Connection: close Content-Type: text/plain abcd
Accroding to 2616, A token is defined as token = 1*<any CHAR except CTLs or separators> separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT Note that (") is defined as a separator. So by definition a value such as "xxxxx" will be interpreted by stripping away the separators. Thus the value " max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry is invalid while the first entry is valid cache control directive. For this reason, the behavior of apache is correct.
Comment #5 says: > Note that (") is defined as a separator. I do not know whether the problem has been fixed since our original report, but please note that the request in Comment #4 does not have quotes. The quotes you see will be eaten by the shell. To Apache, the request looks more like this: GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n Cache-Control: max-age=0 =new\r\n \r\n which contains a valid max-age directive followed by garbage. The original test cases (see attachments) do not have this problem. > So by definition a value such as > "xxxxx" will be interpreted by stripping away the separators. Thus the value " > max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry > is invalid while the first entry is valid cache control directive. Whether quoted strings are not token-like opaque blobs but regular input (that apparently should be re-parsed and interpreted!) preceded and followed by a separator is highly debatable. IMO, the second original test case leaves little doubt that there was a bug here because it uses a quoted string in the value of the extension directive. That usage is a 100% valid extension, right? Again, I do not know whether this has been fixed since. HTH.
|I do not know whether the problem has been fixed since our original report, but |please note that the request in Comment #4 does not have quotes. The quotes you |see will be eaten by the shell. To Apache, the request looks more like this: you are right, my testcases were wrong, but my conclusion did not have anything to do with them. > > So by definition a value such as > > "xxxxx" will be interpreted by stripping away the separators. Thus the value " > > max-age=0 "=blah is interpreted as [max-age=0] [=blah] where the second entry > > is invalid while the first entry is valid cache control directive. > > Whether quoted strings are not token-like opaque blobs but regular input (that > apparently should be re-parsed and interpreted!) preceded and followed by a > separator is highly debatable. Not according to rfc 2616. RFC 2616 states quite clearly that cache-extension should be either token or token=(token|quoted-string) Cache-Control = "Cache-Control" ":" 1#cache-directive cache-directive = cache-request-directive | cache-response-directive cache-request-directive = "no-cache" ; Section 14.9.1 | "no-store" ; Section 14.9.2 | "max-age" "=" delta-seconds ; Section 14.9.3, 14.9.4 | "max-stale" [ "=" delta-seconds ] ; Section 14.9.3 | "min-fresh" "=" delta-seconds ; Section 14.9.3 | "no-transform" ; Section 14.9.5 | "only-if-cached" ; Section 14.9.4 | cache-extension ; Section 14.9.6 cache-extension = token [ "=" ( token | quoted-string ) ] (Note that a quoted string is allowed after the '=' not before.) > IMO, the second original test case leaves little doubt that there was a bug > here because it uses a quoted string in the value of the extension directive. > That usage is a 100% valid extension, right? Again, I do not know whether this > has been fixed since. So with the above definition of token, what is below is not valid, Cache-Control: public, " max-age=8,max-age=8 "=blah\r\n while this would be Cache-Control: public, blah=" max-age=8,max-age=8 "\r\n
> So with the above definition of token, what is below is not valid, > Cache-Control: public, " max-age=8,max-age=8 "=blah\r\n > while this would be > Cache-Control: public, blah=" max-age=8,max-age=8 "\r\n In addition, none of the above HTTP headers contains the "max-age" Cache-Control directive, IMO.
| In addition, none of the above HTTP headers contains the "max-age" | Cache-Control directive, IMO. Your original bug was that the entry that you posted (Cache-control: "xxxx"=blah) was a valid extension directive. But as per the RFC, it is not. The question now, is as to what the httpd should do when faced with an invalid entry. That question is open to further deliberation. IMO that is fair game for httpd to do as it pleases.
> Your original bug was that the entry that you posted (Cache-control: > "xxxx"=blah) was a valid extension directive. Not exactly. There were two test cases in the original bug report. The first case is using the questionable quoted string as the directive name. The second test case does not. I do not recall claiming that both directives are perfectly valid -- I know that one of them is of questionable validity, but that is not the issue in this bug report. > But as per the RFC, it is not. > The question now, is as to what the httpd should do when faced with an invalid > entry. That question is possible for the first test case but not for the second. And even for the first test case, I would not be surprised if httpd actually ignores directives it considers invalid. If that is correct, that the first test case is still good as it illustrates that httpd is not interpreting the invalid directive as invalid.
(In reply to comment #10) > > Your original bug was that the entry that you posted (Cache-control: > > "xxxx"=blah) was a valid extension directive. > > Not exactly. There were two test cases in the original bug report. The first > case is using the questionable quoted string as the directive name. The second > test case does not. I do not recall claiming that both directives are perfectly > valid -- I know that one of them is of questionable validity, but that is not > the issue in this bug report. Now, I am confused, could you please specify the request(s), current response and expected response? (The html is long, and I don't think I am looking at the same lines as you are.) (And can I request you to quote it in text format? html is rather hard quote again in threads.) > > But as per the RFC, it is not. > > The question now, is as to what the httpd should do when faced with an invalid > > entry. > > That question is possible for the first test case but not for the second. > > And even for the first test case, I would not be surprised if httpd actually > ignores directives it considers invalid. If that is correct, that the first > test case is still good as it illustrates that httpd is not interpreting the > invalid directive as invalid.
Created attachment 22484 [details] max-age in the extension name (plain) Saved 1st test case attachment as text per rahul request
Created attachment 22485 [details] max-age in the extension value (plain) Saved test case attachment as text per rahul request. This test case uses the following valid Cache-Control header: Cache-Control: public, foobar=" max-age=8,max-age=8 "\r\n Again, I do not know whether this bug has been fixed since it was reported. HTH.
(In reply to comment #11) > Now, I am confused, could you please specify the request(s), current response > and expected response? (The html is long, and I don't think I am looking at the > same lines as you are.) > > (And can I request you to quote it in text format? html is rather hard quote > again in threads.) Attached test case logs have all the exchanges with the proxy server. I have re-saved them in text format per your request, but they are easier to read if you use your browser to display the HTML attachment instead (you may have to save the HTML attachment as HTML for that to work). The violation is (was?) not in sending a wrong response to a single request but in purging a cached document in reaction to an extension cache-control directive. You have to follow the trace to see that. FWIW, some folks find it easier to read the trace backwards, from the violation to the first request. HTH.
> Created an attachment (id=22485) [details] > max-age in the extension value (plain) > Saved test case attachment as text per rahul request. This test case uses the > following valid Cache-Control header: > > Cache-Control: public, foobar=" max-age=8,max-age=8 "\r\n Thanks a lot, it is much easier now, and I understand where we were not on the same page. > Again, I do not know whether this bug has been fixed since it was reported. Let me know if this is not what you are referring to. ------------------------------------------------------ First a simple request with out directives to make it cache. |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 18:52:36 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Age: 30 Connection: close Content-Type: text/plain abcd as snooped in the backend. --> [ GET /tst.txt HTTP/1.1 Host: webproxy.india.sun.com:8000 Cache-Control: "max-age=0"=me Via: 1.0 agneyam:8000 Connection: Keep-Alive ] ------------------------------------------------------ Now trying with a vaild cache-control max-age (valid behavior). |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: max-age=0\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 18:53:43 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT Connection: close Content-Type: text/plain abcd --> [ GET /tst.txt HTTP/1.1 Host: webproxy.india.sun.com:8000 Cache-Control: max-age=0 If-None-Match: "5-48b3e521" If-Modified-Since: Tue, 26 Aug 2008 11:12:33 GMT Via: 1.0 agneyam:8000 Connection: Keep-Alive ] <-- [ HTTP/1.1 304 Use local copy Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Date: Tue, 26 Aug 2008 18:53:43 GMT Etag: "5-48b3e521" ] ------------------------------------------------------ Now trying an invalid cache-control directive, |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: \"max-age=0\"\r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 18:53:43 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Age: 2 Connection: close Content-Type: text/plain abcd --> No request to the back end observed. ------------------------------------------------------ Now trying an second invalid cache-control directive, |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: \" max-age=0 \"=foobar \r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 18:58:18 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Age: 115 Connection: close Content-Type: text/plain abcd --> No request to the back end observed. ------------------------------------------------------ Trying a third invalid cache-control directive, |echo "GET http://webproxy.india.sun.com:8000/tst.txt HTTP/1.0\r\nCache-Control: foobar=\" max-age=0 \" \r\n\r\n" | nc 0 8080 HTTP/1.1 200 OK Date: Tue, 26 Aug 2008 18:58:18 GMT Server: Sun-Java-System-Web-Proxy-Server/4.0.4 Last-Modified: Tue, 26 Aug 2008 11:12:33 GMT Content-length: 5 Etag: "5-48b3e521" Accept-ranges: bytes Via: 1.0 agneyam:8000 Age: 163 Connection: close Content-Type: text/plain abcd --> No request to the back end observed. ------------------------------------------------------ And no cache-eviction observed. Is my verification correct?, if it is, then it is not present in trunk any more (though may be present in the earlier versions |> 2.0.54 < trunk| ) thanks for the bug report.
I do not see any problems with your verification steps. Looks like this bug was fixed.
Verified fixed in 2.2.9 closing it as fixed.
Undo spam change