You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2009/09/17 05:16:57 UTC

svn commit: r816033 - /couchdb/trunk/src/couchdb/couch_httpd.erl

Author: davisp
Date: Thu Sep 17 03:16:54 2009
New Revision: 816033

URL: http://svn.apache.org/viewvc?rev=816033&view=rev
Log:
Fixes COUCHDB-504

Thanks to Bob Dionne for figuring out the underlying cause. Thanks to Benoit for making my initial patch alot cleaner.

This version is basically Benoit's patch with two extra conditions for sending the Keep-Alive header. It must be a HTTP/1.0 connection and there must not be a Connection header already defined.


Modified:
    couchdb/trunk/src/couchdb/couch_httpd.erl

Modified: couchdb/trunk/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd.erl?rev=816033&r1=816032&r2=816033&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd.erl Thu Sep 17 03:16:54 2009
@@ -377,10 +377,28 @@
     Resp:send(Data),
     {ok, Resp}.
 
+no_resp_conn_header([]) ->
+    true;
+no_resp_conn_header([{Hdr, _}|Rest]) ->
+    case string:to_lower(Hdr) of
+        "connection" -> false;
+        _ -> no_resp_conn_header(Rest)
+    end.
+
+http_1_0_keep_alive(Req, Headers) ->
+    KeepOpen = Req:should_close() == false,
+    IsHttp10 = Req:get(version) == {1, 0},
+    NoRespHeader = no_resp_conn_header(Headers),
+    case KeepOpen andalso IsHttp10 andalso NoRespHeader of
+        true -> [{"Connection", "Keep-Alive"} | Headers];
+        false -> Headers
+    end.
+
 start_chunked_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers) ->
     log_request(Req, Code),
     couch_stats_collector:increment({httpd_status_codes, Code}),
-    Resp = MochiReq:respond({Code, Headers ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers), chunked}),
+    Headers2 = http_1_0_keep_alive(MochiReq, Headers),
+    Resp = MochiReq:respond({Code, Headers2 ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers2), chunked}),
     case MochiReq:get(method) of
     'HEAD' -> throw({http_head_abort, Resp});
     _ -> ok
@@ -394,11 +412,12 @@
 send_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers, Body) ->
     log_request(Req, Code),
     couch_stats_collector:increment({httpd_status_codes, Code}),
+    Headers2 = http_1_0_keep_alive(MochiReq, Headers),
     if Code >= 400 ->
         ?LOG_DEBUG("httpd ~p error response:~n ~s", [Code, Body]);
     true -> ok
     end,
-    {ok, MochiReq:respond({Code, Headers ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers), Body})}.
+    {ok, MochiReq:respond({Code, Headers2 ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers2), Body})}.
 
 send_method_not_allowed(Req, Methods) ->
     send_error(Req, 405, [{"Allow", Methods}], <<"method_not_allowed">>, ?l2b("Only " ++ Methods ++ " allowed")).



Re: svn commit: r816033 - /couchdb/trunk/src/couchdb/couch_httpd.erl

Posted by Christopher Lenz <cm...@gmx.de>.
On 17.09.2009, at 05:16, davisp@apache.org wrote:
> Author: davisp
> Date: Thu Sep 17 03:16:54 2009
> New Revision: 816033
>
> URL: http://svn.apache.org/viewvc?rev=816033&view=rev
> Log:
> Fixes COUCHDB-504
>
> Thanks to Bob Dionne for figuring out the underlying cause. Thanks  
> to Benoit for making my initial patch alot cleaner.
>
> This version is basically Benoit's patch with two extra conditions  
> for sending the Keep-Alive header. It must be a HTTP/1.0 connection  
> and there must not be a Connection header already defined.

This looks like something that would be nice to patch upstream, no?

> Modified:
>    couchdb/trunk/src/couchdb/couch_httpd.erl
>
> Modified: couchdb/trunk/src/couchdb/couch_httpd.erl
> URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd.erl?rev=816033&r1=816032&r2=816033&view=diff
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- couchdb/trunk/src/couchdb/couch_httpd.erl (original)
> +++ couchdb/trunk/src/couchdb/couch_httpd.erl Thu Sep 17 03:16:54 2009
> @@ -377,10 +377,28 @@
>     Resp:send(Data),
>     {ok, Resp}.
>
> +no_resp_conn_header([]) ->
> +    true;
> +no_resp_conn_header([{Hdr, _}|Rest]) ->
> +    case string:to_lower(Hdr) of
> +        "connection" -> false;
> +        _ -> no_resp_conn_header(Rest)
> +    end.
> +
> +http_1_0_keep_alive(Req, Headers) ->
> +    KeepOpen = Req:should_close() == false,
> +    IsHttp10 = Req:get(version) == {1, 0},
> +    NoRespHeader = no_resp_conn_header(Headers),
> +    case KeepOpen andalso IsHttp10 andalso NoRespHeader of
> +        true -> [{"Connection", "Keep-Alive"} | Headers];
> +        false -> Headers
> +    end.
> +
> start_chunked_response(#httpd{mochi_req=MochiReq}=Req, Code,  
> Headers) ->
>     log_request(Req, Code),
>     couch_stats_collector:increment({httpd_status_codes, Code}),
> -    Resp = MochiReq:respond({Code, Headers ++ server_header() ++  
> couch_httpd_auth:cookie_auth_header(Req, Headers), chunked}),
> +    Headers2 = http_1_0_keep_alive(MochiReq, Headers),
> +    Resp = MochiReq:respond({Code, Headers2 ++ server_header() ++  
> couch_httpd_auth:cookie_auth_header(Req, Headers2), chunked}),
>     case MochiReq:get(method) of
>     'HEAD' -> throw({http_head_abort, Resp});
>     _ -> ok
> @@ -394,11 +412,12 @@
> send_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers, Body) ->
>     log_request(Req, Code),
>     couch_stats_collector:increment({httpd_status_codes, Code}),
> +    Headers2 = http_1_0_keep_alive(MochiReq, Headers),
>     if Code >= 400 ->
>         ?LOG_DEBUG("httpd ~p error response:~n ~s", [Code, Body]);
>     true -> ok
>     end,
> -    {ok, MochiReq:respond({Code, Headers ++ server_header() ++  
> couch_httpd_auth:cookie_auth_header(Req, Headers), Body})}.
> +    {ok, MochiReq:respond({Code, Headers2 ++ server_header() ++  
> couch_httpd_auth:cookie_auth_header(Req, Headers2), Body})}.
>
> send_method_not_allowed(Req, Methods) ->
>     send_error(Req, 405, [{"Allow", Methods}],  
> <<"method_not_allowed">>, ?l2b("Only " ++ Methods ++ " allowed")).

--
Christopher Lenz
   cmlenz at gmx.de
   http://www.cmlenz.net/