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;

Reply via email to