You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by kx...@apache.org on 2015/09/17 12:26:44 UTC
couch commit: updated refs/heads/master to c63796e
Repository: couchdb-couch
Updated Branches:
refs/heads/master b8b996832 -> c63796e4e
Fix duplicated Content-Type for show/update functions
When a show/update function returned data it added a
"Content-Type: application/json" header by itself. Then
couch_httpd added some default headers (including a yet
another "application/json" one).
This diff will add default chttpd headers only when
same headers are not yet present in the response.
This closes #55
COUCHDB-1876
Signed-off-by: Alexander Shorin <kx...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/c63796e4
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/c63796e4
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/c63796e4
Branch: refs/heads/master
Commit: c63796e4e5b7f649d461f6b72494dc9f9246a59e
Parents: b8b9968
Author: Artur Mazurek <ar...@gmail.com>
Authored: Mon May 25 15:19:53 2015 +0100
Committer: Alexander Shorin <kx...@apache.org>
Committed: Thu Sep 17 13:24:54 2015 +0300
----------------------------------------------------------------------
src/couch_httpd.erl | 103 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 93 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/c63796e4/src/couch_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_httpd.erl b/src/couch_httpd.erl
index eee1001..d1e9447 100644
--- a/src/couch_httpd.erl
+++ b/src/couch_httpd.erl
@@ -747,23 +747,17 @@ send_json(Req, Code, Value) ->
send_json(Req, Code, Headers, Value) ->
initialize_jsonp(Req),
- DefaultHeaders = [
- {"Content-Type", negotiate_content_type(Req)},
- {"Cache-Control", "must-revalidate"}
- ],
+ AllHeaders = maybe_add_default_headers(Req, Headers),
Body = [start_jsonp(), ?JSON_ENCODE(Value), end_jsonp(), $\n],
- send_response(Req, Code, DefaultHeaders ++ Headers, Body).
+ send_response(Req, Code, AllHeaders, Body).
start_json_response(Req, Code) ->
start_json_response(Req, Code, []).
start_json_response(Req, Code, Headers) ->
initialize_jsonp(Req),
- DefaultHeaders = [
- {"Content-Type", negotiate_content_type(Req)},
- {"Cache-Control", "must-revalidate"}
- ],
- {ok, Resp} = start_chunked_response(Req, Code, DefaultHeaders ++ Headers),
+ AllHeaders = maybe_add_default_headers(Req, Headers),
+ {ok, Resp} = start_chunked_response(Req, Code, AllHeaders),
case start_jsonp() of
[] -> ok;
Start -> send_chunk(Resp, Start)
@@ -774,6 +768,19 @@ end_json_response(Resp) ->
send_chunk(Resp, end_jsonp() ++ [$\n]),
last_chunk(Resp).
+maybe_add_default_headers(ForRequest, ToHeaders) ->
+ DefaultHeaders = [
+ {"Content-Type", negotiate_content_type(ForRequest)},
+ {"Cache-Control", "must-revalidate"}
+ ],
+ lists:foldl(fun maybe_add_header/2, ToHeaders, DefaultHeaders).
+
+maybe_add_header({HeaderName, HeaderValue}, ToHeaders) ->
+ case lists:keyfind(HeaderName, 1, ToHeaders) of
+ false -> ToHeaders ++ [{HeaderName, HeaderValue}];
+ _Found -> ToHeaders
+ end.
+
initialize_jsonp(Req) ->
case get(jsonp) of
undefined -> put(jsonp, qs_value(Req, "callback", no_jsonp));
@@ -1120,3 +1127,79 @@ validate_bind_address(Address) ->
{ok, _} -> ok;
_ -> throw({error, invalid_bind_address})
end.
+
+
+%%%%%%%% module tests below %%%%%%%%
+
+-ifdef(TEST).
+-include_lib("couch/include/couch_eunit.hrl").
+
+maybe_add_header_test_() ->
+ Cases = [
+ {[], % initial headers
+ {"K1", "V1"}, % header to add
+ [{"K1", "V1"}], % expected result
+ "Adding to empty headers"},
+
+ {[{"K1", "V1"}],
+ {"K2", "V2"},
+ [{"K1", "V1"}, {"K2", "V2"}],
+ "Adding header to 1 element headers list"},
+
+ {[{"K1", "V1"}],
+ {"K1", "V2"},
+ [{"K1", "V1"}],
+ "Trying to add same header to 1 element headers list"},
+
+ {[{"K1", "V1"}, {"K2", "V2"}],
+ {"K1", "V2"},
+ [{"K1", "V1"}, {"K2", "V2"}],
+ "Trying to add same header to 2 element headers list"},
+
+ {[{"K1", "V1"}, {"K2", "V2"}],
+ {"K3", "V3"},
+ [{"K1", "V1"}, {"K2", "V2"}, {"K3", "V3"}],
+ "Adding header to 2 elements headers list"}
+ ],
+ Tests = lists:map(fun({InitialHeaders, HeaderToAdd, ProperResult, Desc}) ->
+ {Desc,
+ ?_assertEqual(ProperResult,
+ maybe_add_header(HeaderToAdd, InitialHeaders))}
+ end, Cases),
+ {"Tests adding a header to a list of headers", Tests}.
+
+maybe_add_default_headers_test_() ->
+ DummyRequest = [],
+ NoCache = {"Cache-Control", "no-cache"},
+ ApplicationJson = {"Content-Type", "application/json"},
+ % couch_httpd uses process dictionary to check if currently in a
+ % json serving method. Defaults to 'application/javascript' otherwise.
+ % Therefore must-revalidate and application/javascript should be added
+ % by chttpd if such headers are not present
+ MustRevalidate = {"Cache-Control", "must-revalidate"},
+ ApplicationJavascript = {"Content-Type", "application/javascript"},
+ Cases = [
+ {[],
+ [ApplicationJavascript, MustRevalidate],
+ "Should add Content-Type and Cache-Control to empty heaeders"},
+
+ {[NoCache],
+ [NoCache, ApplicationJavascript],
+ "Should add Content-Type only if Cache-Control is present"},
+
+ {[ApplicationJson],
+ [ApplicationJson, MustRevalidate],
+ "Should add Cache-Control if Content-Type is present"},
+
+ {[NoCache, ApplicationJson],
+ [NoCache, ApplicationJson],
+ "Should not add headers if Cache-Control and Content-Type are there"}
+ ],
+ Tests = lists:map(fun({InitialHeaders, ProperResult, Desc}) ->
+ {Desc,
+ ?_assertEqual(ProperResult,
+ maybe_add_default_headers(DummyRequest, InitialHeaders))}
+ end, Cases),
+ {"Tests adding default headers", Tests}.
+
+-endif.