There are broken servers out there that insist on receiving HTTP/1.1
requests.
This patch adds a new force_http_1p1_request acl-driven option to
squid.conf.
When the HTTP request matches the specified ACL, Squid uses "HTTP/1.1"
HTTP-Version string in the request sent to the server. The affected
requests have "HTTP/1.1" HTTP-Version token but are not
altered in any other way.
The option apply after the request adaptation (if any)
Please take care to the "#if WHEN_SQUID_IS_HTTP1_1" block in
HttpMsg.cc file which was disabled. This block allow squid to consider
a connection to the HTTP server as persistent in the case the
"Connection: close" header does not exist in the case of HTTP 1.1 replies.
I did not found any problem with this but maybe I am loosing something.
This is a Measurement Factory project.
Regards,
Christos
=== modified file 'src/HttpMsg.cc'
--- src/HttpMsg.cc 2009-12-31 11:46:41 +0000
+++ src/HttpMsg.cc 2010-02-19 21:06:10 +0000
@@ -321,7 +321,6 @@
int
httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr)
{
-#if WHEN_SQUID_IS_HTTP1_1
if ((http_ver.major >= 1) && (http_ver.minor >= 1)) {
/*
@@ -329,10 +328,7 @@
* a "Connection: close" header.
*/
return !httpHeaderHasConnDir(hdr, "close");
- } else
-#else
- {
-#endif
+ } else {
/*
* Persistent connections in Netscape 3.x are allegedly broken,
* return false if it is a browser connection. If there is a
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2010-02-07 03:38:46 +0000
+++ src/cf.data.pre 2010-02-09 22:26:58 +0000
@@ -6809,4 +6809,22 @@
Whether to lookup the EUI or MAC address of a connected client.
DOC_END
+NAME: force_http_1p1_request
+TYPE: acl_access
+LOC: Config.accessList.force_http_1p1_request
+DEFAULT: none
+DOC_START
+ When the HTTP request matches the specified ACL, Squid uses "HTTP/1.1"
+ HTTP-Version string in the request sent to the server. The affected
+ responses have "HTTP/1.1" HTTP-Version token but are not
+ altered in any other way.
+ The ACL is checked after request adaptation, if any.
+NOCOMMENT_START
+#force HTTP/1.1 request
+# acl expects_1p1 method OPTIONS IamBroken
+# force_http_1p1_request expects_1p1
+NOCOMMENT_END
+DOC_END
+
+
EOF
=== modified file 'src/forward.h'
--- src/forward.h 2009-09-02 13:09:29 +0000
+++ src/forward.h 2010-02-19 21:06:10 +0000
@@ -53,6 +53,9 @@
void ftpPasvFailed(bool val) { flags.ftp_pasv_failed = val; }
+ bool checkedHttp1p1Acl() { return flags.checked_http_1p1_acl; }
+ void checkedHttp1p1Acl(bool val) { flags.checked_http_1p1_acl = val; }
+
static void serversFree(FwdServer **);
private:
@@ -96,6 +99,7 @@
unsigned int dont_retry:1;
unsigned int ftp_pasv_failed:1;
unsigned int forward_completed:1;
+ unsigned int checked_http_1p1_acl:1;
} flags;
IpAddress src; /* Client address for this connection. Needed for transparent operations. */
=== modified file 'src/http.cc'
--- src/http.cc 2010-02-06 06:32:11 +0000
+++ src/http.cc 2010-02-19 21:36:08 +0000
@@ -113,6 +113,8 @@
proxy_req->port = _peer->http_port;
+ proxy_req->http_ver = request->http_ver;
+
proxy_req->flags = orig_request->flags;
proxy_req->lastmod = orig_request->lastmod;
@@ -1924,11 +1926,10 @@
http_state_flags stateFlags)
{
const int offset = mb->size;
- HttpVersion httpver(1,0);
mb->Printf("%s %s HTTP/%d.%d\r\n",
RequestMethodStr(aRequest->method),
aRequest->urlpath.size() ? aRequest->urlpath.termedBuf() : "/",
- httpver.major,httpver.minor);
+ aRequest->http_ver.major, aRequest->http_ver.minor);
/* build and pack headers */
{
HttpHeader hdr(hoRequest);
@@ -2022,10 +2023,34 @@
return true;
}
+void EnforceHttp1p1Acl (int rv, void *aFwd)
+{
+ FwdState *fwd = static_cast<FwdState *>(aFwd);
+ if (rv) {
+ fwd->request->http_ver = HttpVersion(1, 1);
+ }
+ else {
+ fwd->request->http_ver = HttpVersion(1, 0);
+ }
+
+ fwd->checkedHttp1p1Acl(true);
+ httpStart(fwd);
+}
+
+
void
httpStart(FwdState *fwd)
{
debugs(11, 3, "httpStart: \"" << RequestMethodStr(fwd->request->method) << " " << fwd->entry->url() << "\"" );
+
+ if (Config.accessList.force_http_1p1_request && !fwd->checkedHttp1p1Acl()) {
+ ACLFilledChecklist *http1p1Checklist = new ACLFilledChecklist(
+ Config.accessList.force_http_1p1_request, fwd->request, NULL);
+
+ http1p1Checklist->nonBlockingCheck(EnforceHttp1p1Acl, fwd);
+ return;
+ }
+
HttpStateData *httpState = new HttpStateData(fwd);
if (!httpState->sendRequest()) {
=== modified file 'src/http.h'
--- src/http.h 2009-07-02 16:36:36 +0000
+++ src/http.h 2010-02-19 21:06:10 +0000
@@ -44,7 +44,7 @@
{
public:
- HttpStateData(FwdState *);
+ HttpStateData(FwdState *fwd);
~HttpStateData();
static void httpBuildRequestHeader(HttpRequest * request,
=== modified file 'src/structs.h'
--- src/structs.h 2010-02-07 03:38:46 +0000
+++ src/structs.h 2010-02-19 21:06:10 +0000
@@ -497,6 +497,8 @@
#if ICAP_CLIENT
acl_access* icap;
#endif
+
+ acl_access* force_http_1p1_request;
} accessList;
acl_deny_info_list *denyInfoList;
authConfig authConfiguration;