]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
* mod_proxy_http: Correctly forward unexpected interim (HTTP 1xx) responses
authorJim Jagielski <jim@apache.org>
Sat, 8 Dec 2007 14:01:47 +0000 (14:01 +0000)
committerJim Jagielski <jim@apache.org>
Sat, 8 Dec 2007 14:01:47 +0000 (14:01 +0000)
      incorporating ap_send_interim_response core API
          PR 16518

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@602468 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/mod/mod_proxy_http.xml
include/ap_mmn.h
include/http_protocol.h
modules/proxy/mod_proxy_http.c
server/protocol.c

diff --git a/CHANGES b/CHANGES
index a3916d9bda27547fb17108f273d975d36736a220..9636b790b6ae36c0a2c925e9c11c9858dc500ec5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,11 @@ Changes with Apache 2.2.7
   *) Various code cleanups. PR 38699, 39518, 42005, 42006, 42007, 42008, 42009
      [Christophe Jaillet <christophe.jaillet wanadoo.fr>]
 
+  *) mod_proxy_http: Correctly forward unexpected interim (HTTP 1xx)
+     responses from the backend according to RFC2616.  But make it
+     configurable in case something breaks on it.
+     PR 16518 [Nick Kew]
+
   *) rotatelogs: Change command-line parsing to report more types
      of errors.  Allow local timestamps to be used when rotating based
      on file size.  [Jeff Trawick]
diff --git a/STATUS b/STATUS
index 54f8821ffe8286e311a25c2ed61a5c88f3282256..b53bb6bce2becf43bffc4ae01e208f0cfb5b4ada 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -79,18 +79,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  * mod_proxy_http: Correctly forward unexpected interim (HTTP 1xx) responses
-    incorporating ap_send_interim_response core API
-    PR 16518
-    trunk:
-      http://svn.apache.org/viewvc?view=rev&revision=582630
-      http://svn.apache.org/viewvc?view=rev&revision=582652
-      http://svn.apache.org/viewvc?view=rev&revision=582631
-      http://svn.apache.org/viewvc?view=rev&revision=588806
-    2.2.x:
-      http://people.apache.org/~niq/16508.patch
-    +1: niq, rpluem, jim
-
   * http_filters: Fix handling of unrecognised Transfer Encodings
     PR 43882
     http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/http_filters.c?r1=592951&r2=599137
index 528f03b0438cadd380476fd8f7c8937f607debe8..60430671edb9c5d40473e7fcd6d05cf3d15e6243 100644 (file)
         request bodies to be sent to the backend using chunked transfer
         encoding.  This allows the request to be efficiently streamed,
         but requires that the backend server supports HTTP/1.1.</dd>
+        <dt>proxy-interim-response</dt>
+        <dd>This variable takes values <code>RFC</code> or
+        <code>Suppress</code>.  Earlier httpd versions would suppress
+        HTTP interim (1xx) responses sent from the backend.  This is
+        technically a violation of the HTTP protocol.  In practice,
+        if a backend sends an interim response, it may itself be
+        extending the protocol in a manner we know nothing about,
+        or just broken.  So this is now configurable: set
+        <code>proxy-interim-response RFC</code> to be fully protocol
+        compliant, or <code>proxy-interim-response Suppress</code>
+        to suppress interim responses.</dd>
     </dl>
 </section>
 
index a37c44a2d6fe90dcc5f1fbcabcdbee52cf7fdd03..5b7941904f63f3b63c300cfa8cd956a11ad71989 100644 (file)
  * 20051115.6 (2.2.7)  Added retry_set to proxy_worker (minor)
  * 20051115.7 (2.2.7)  Added conn_rec::clogging_input_filters (minor)
  * 20051115.8 (2.2.7)  Added flags to proxy_alias (minor)
+ * 20051115.9 (2.2.7)  Add ap_send_interim_response API
  *
  */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20051115
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 8                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 9                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index e8355e17a675c0593ad5183e5f4229a4269fd79c..276d09bf98fb6b23acc809f3e0d699ed34a170e7 100644 (file)
@@ -664,6 +664,13 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r
  * @param sub_r Subrequest that is now compete
  */
 AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub_r);
+
+/**
+ * Send an interim (HTTP 1xx) response immediately.
+ * @param r The request
+ * @param send_headers Whether to send&clear headers in r->headers_out
+ */
+AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers);
                                                                                 
 #ifdef __cplusplus
 }
index 774852eed404236da0fca8c12fff7d377262b103..e5f654bb9b2a7c7a2504afe8587ab877b45f7c01 100644 (file)
@@ -1520,9 +1520,33 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
 
         interim_response = ap_is_HTTP_INFO(r->status);
         if (interim_response) {
+            /* RFC2616 tells us to forward this.
+             *
+             * OTOH, an interim response here may mean the backend
+             * is playing sillybuggers.  The Client didn't ask for
+             * it within the defined HTTP/1.1 mechanisms, and if
+             * it's an extension, it may also be unsupported by us.
+             *
+             * There's also the possibility that changing existing
+             * behaviour here might break something.
+             *
+             * So let's make it configurable.
+             */
+            const char *policy = apr_table_get(r->subprocess_env,
+                                               "proxy-interim-response");
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,
                          "proxy: HTTP: received interim %d response",
                          r->status);
+            if (!policy || !strcasecmp(policy, "RFC")) {
+                ap_send_interim_response(r, 1);
+            }
+            /* FIXME: refine this to be able to specify per-response-status
+             * policies and maybe also add option to bail out with 502
+             */
+            else if (strcasecmp(policy, "Suppress")) {
+                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
+                             "undefined proxy interim response policy");
+            }
         }
         /* Moved the fixups of Date headers and those affected by
          * ProxyPassReverse/etc from here to ap_proxy_read_headers
index b7145bb7df13e777c9447b9fdc575d971900b6d9..d58dd8c2229abe32cb3b9f74daa7a5f3806588b8 100644 (file)
@@ -1633,6 +1633,44 @@ AP_DECLARE(void) ap_set_last_modified(request_rec *r)
     }
 }
 
+typedef struct hdr_ptr {
+    ap_filter_t *f;
+    apr_bucket_brigade *bb;
+} hdr_ptr;
+
+static int send_header(void *data, const char *key, const char *val)
+{
+    ap_fputstrs(((hdr_ptr*)data)->f, ((hdr_ptr*)data)->bb,
+                key, ": ", val, CRLF, NULL);
+    return 1;
+}
+
+AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers)
+{
+    hdr_ptr x;
+
+    if (r->proto_num < 1001) {
+        /* don't send interim response to HTTP/1.0 Client */
+        return;
+    }
+    if (!ap_is_HTTP_INFO(r->status)) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+                      "Status is %d - not sending interim response", r->status);
+        return;
+    }
+
+    x.f = r->connection->output_filters;
+    x.bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    ap_fputstrs(x.f, x.bb, AP_SERVER_PROTOCOL, " ", r->status_line, CRLF, NULL);
+    if (send_headers) {
+        apr_table_do(send_header, &x, r->headers_out, NULL);
+        apr_table_clear(r->headers_out);
+    }
+    ap_fputs(x.f, x.bb, CRLF);
+    ap_fflush(x.f, x.bb);
+    apr_brigade_destroy(x.bb);
+}
+
 AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
                           (request_rec *r), (r), OK, DECLINED)
 AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,