couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From iil...@apache.org
Subject [1/5] chttpd commit: updated refs/heads/master to ad754a3
Date Thu, 03 Mar 2016 20:06:06 GMT
Repository: couchdb-chttpd
Updated Branches:
  refs/heads/master 41ac33a08 -> ad754a387


Introduce vhosts configuration into CORS

In order to remove code duplication we move vhosts support
from couch_http_cors into chttpd_cors. We also dispatch
chttpd:send_response to couch_http which does call chttpd_cors:headers.
In order to avoid double injection of CORS headers we check for existance of
"Access-Control-Allow-Origin" in response headers.

COUCHDB-2945


Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/17458082
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/17458082
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/17458082

Branch: refs/heads/master
Commit: 174580824e7c438095448454b0e1a187d7815fcf
Parents: 41ac33a
Author: ILYA Khlopotov <iilyak@ca.ibm.com>
Authored: Tue Feb 9 13:22:05 2016 -0800
Committer: ILYA Khlopotov <iilyak@ca.ibm.com>
Committed: Thu Mar 3 11:56:59 2016 -0800

----------------------------------------------------------------------
 src/chttpd.erl          | 28 +++++++++++-------------
 src/chttpd_cors.erl     | 51 ++++++++++++++++++++++++++++++++++++++------
 src/chttpd_external.erl |  9 ++++----
 3 files changed, 61 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/17458082/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index e47c49f..ffdc928 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -25,6 +25,7 @@
     server_header/0, start_chunked_response/3,send_chunk/2,
     start_response_length/4, send/2, start_json_response/2,
     start_json_response/3, end_json_response/1, send_response/4,
+    send_response_no_cors/4,
     send_method_not_allowed/2, send_error/2, send_error/4, send_redirect/2,
     send_chunked_error/2, send_json/2,send_json/3,send_json/4,
     validate_ctype/2]).
@@ -643,9 +644,8 @@ etag_respond(Req, CurrentEtag, RespFun) ->
     case etag_match(Req, CurrentEtag) of
     true ->
         % the client has this in their cache.
-        Headers0 = [{"Etag", CurrentEtag}],
-        Headers1 = chttpd_cors:headers(Req, Headers0),
-        chttpd:send_response(Req, 304, Headers1, <<>>);
+        Headers = [{"Etag", CurrentEtag}],
+        chttpd:send_response(Req, 304, Headers, <<>>);
     false ->
         % Run the function.
         RespFun()
@@ -689,12 +689,13 @@ send_chunk(Resp, Data) ->
     Resp:write_chunk(Data),
     {ok, Resp}.
 
-send_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers0, Body) ->
-    couch_stats:increment_counter([couchdb, httpd_status_codes, Code]),
-    Headers = Headers0 ++ server_header() ++
-	[timing(), reqid() | couch_httpd_auth:cookie_auth_header(Req, Headers0)],
-    {ok, MochiReq:respond({Code, Headers, Body})}.
+send_response(Req, Code, Headers0, Body) ->
+    Headers1 = [timing(), reqid() | Headers0],
+    couch_httpd:send_response(Req, Code, Headers1, Body).
 
+send_response_no_cors(Req, Code, Headers0, Body) ->
+    Headers1 = [timing(), reqid() | Headers0],
+    couch_httpd:send_response_no_cors(Req, Code, Headers1, Body).
 
 send_method_not_allowed(Req, Methods) ->
     send_error(Req, 405, [{"Allow", Methods}], <<"method_not_allowed">>,
@@ -708,16 +709,14 @@ send_json(Req, Code, Value) ->
 
 send_json(Req, Code, Headers0, Value) ->
     Headers1 = [timing(), reqid() | Headers0],
-    Headers2 = chttpd_cors:headers(Req, Headers1),
-    couch_httpd:send_json(Req, Code, Headers2, Value).
+    couch_httpd:send_json(Req, Code, Headers1, Value).
 
 start_json_response(Req, Code) ->
     start_json_response(Req, Code, []).
 
 start_json_response(Req, Code, Headers0) ->
     Headers1 = [timing(), reqid() | Headers0],
-    Headers2 = chttpd_cors:headers(Req, Headers1),
-    couch_httpd:start_json_response(Req, Code, Headers2).
+    couch_httpd:start_json_response(Req, Code, Headers1).
 
 end_json_response(Resp) ->
     couch_httpd:end_json_response(Resp).
@@ -989,9 +988,8 @@ send_chunked_error(Resp, Error) ->
     send_chunk(Resp, []).
 
 send_redirect(Req, Path) ->
-    Headers0 = [{"Location", chttpd:absolute_uri(Req, Path)}],
-    Headers1 = chttpd_cors:headers(Req, Headers0),
-    send_response(Req, 301, Headers1, <<>>).
+    Headers = [{"Location", chttpd:absolute_uri(Req, Path)}],
+    send_response(Req, 301, Headers, <<>>).
 
 server_header() ->
     couch_httpd:server_header().

http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/17458082/src/chttpd_cors.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_cors.erl b/src/chttpd_cors.erl
index 83cfc53..0cb2061 100644
--- a/src/chttpd_cors.erl
+++ b/src/chttpd_cors.erl
@@ -38,7 +38,7 @@ maybe_handle_preflight_request(Req) ->
         not_preflight ->
             not_preflight;
         {ok, PreflightHeaders} ->
-            chttpd:send_response(Req, 204, PreflightHeaders, <<>>)
+            chttpd:send_response_no_cors(Req, 204, PreflightHeaders, <<>>)
     end.
 
 
@@ -227,11 +227,13 @@ simple_headers(Headers) ->
     LCHeaders = [to_lower(H) || H <- Headers],
     lists:filter(fun(H) -> lists:member(H, ?SIMPLE_HEADERS) end, LCHeaders).
 
+
 to_lower(String) when is_binary(String) ->
     to_lower(?b2l(String));
 to_lower(String) ->
     string:to_lower(String).
 
+
 handle_headers(_Config, _Origin, []) ->
     [];
 handle_headers(Config, Origin, AcceptedOrigins) ->
@@ -272,28 +274,32 @@ allow_credentials(Config, Origin) ->
     get_origin_config(Config, Origin, <<"allow_credentials">>,
         ?CORS_DEFAULT_ALLOW_CREDENTIALS).
 
-get_cors_config(#httpd{cors_config = undefined}) ->
+
+get_cors_config(#httpd{cors_config = undefined, mochi_req = MochiReq}) ->
+    Host = couch_httpd_vhost:host(MochiReq),
+
     EnableCors = config:get("httpd", "enable_cors", "false") =:= "true",
-    AllowCredentials = config:get("cors", "credentials", "false") =:= "true",
-    AllowHeaders = case config:get("cors", "headers", undefined) of
+    AllowCredentials = cors_config(Host, "credentials", "false") =:= "true",
+
+    AllowHeaders = case cors_config(Host, "headers", undefined) of
         undefined ->
             ?SUPPORTED_HEADERS;
         AllowHeaders0 ->
             [to_lower(H) || H <- split_list(AllowHeaders0)]
     end,
-    AllowMethods = case config:get("cors", "methods", undefined) of
+    AllowMethods = case cors_config(Host, "methods", undefined) of
         undefined ->
             ?SUPPORTED_METHODS;
         AllowMethods0 ->
             split_list(AllowMethods0)
     end,
-    ExposedHeaders = case config:get("cors", "exposed_headers", undefined) of
+    ExposedHeaders = case cors_config(Host, "exposed_headers", undefined) of
         undefined ->
             ?COUCH_HEADERS;
         ExposedHeaders0 ->
             [to_lower(H) || H <- split_list(ExposedHeaders0)]
     end,
-    Origins0 = binary_split_list(config:get("cors", "origins", [])),
+    Origins0 = binary_split_list(cors_config(Host, "origins", [])),
     Origins = [{O, {[]}} || O <- Origins0],
     [
         {<<"enable_cors">>, EnableCors},
@@ -306,6 +312,37 @@ get_cors_config(#httpd{cors_config = undefined}) ->
 get_cors_config(#httpd{cors_config = Config}) ->
     Config.
 
+
+cors_config(Host, Key, Default) ->
+    config:get(cors_section(Host), Key,
+        config:get("cors", Key, Default)).
+
+
+cors_section(Host0) ->
+    {Host, _Port} = split_host_port(Host0),
+    "cors:" ++ Host.
+
+split_host_port(HostAsString) ->
+    % split at semicolon ":"
+    Split = string:rchr(HostAsString, $:),
+    split_host_port(HostAsString, Split).
+
+split_host_port(HostAsString, 0) ->
+    % no semicolon
+    {HostAsString, '*'};
+split_host_port(HostAsString, N) ->
+    HostPart = string:substr(HostAsString, 1, N-1),
+    % parse out port
+    % is there a nicer way?
+    case (catch erlang:list_to_integer(string:substr(HostAsString,
+                    N+1, length(HostAsString)))) of
+    {'EXIT', _} ->
+        {HostAsString, '*'};
+    Port ->
+        {HostPart, Port}
+    end.
+
+
 is_cors_enabled(Config) ->
     case get(disable_couch_httpd_cors) of
         undefined ->

http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/17458082/src/chttpd_external.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_external.erl b/src/chttpd_external.erl
index 8521676..f9bebed 100644
--- a/src/chttpd_external.erl
+++ b/src/chttpd_external.erl
@@ -157,16 +157,15 @@ send_external_response(Req, Response) ->
         code = Code,
         data = Data,
         ctype = CType,
-        headers = Headers,
+        headers = Headers0,
         json = Json
     } = parse_external_response(Response),
-    Headers1 = default_or_content_type(CType, Headers),
-    Headers2 = chttpd_cors:headers(Req, Headers1),
+    Headers1 = default_or_content_type(CType, Headers0),
     case Json of
     nil ->
-        chttpd:send_response(Req, Code, Headers2, Data);
+        chttpd:send_response(Req, Code, Headers1, Data);
     Json ->
-        chttpd:send_json(Req, Code, Headers2, Json)
+        chttpd:send_json(Req, Code, Headers1, Json)
     end.
 
 parse_external_response({Response}) ->


Mime
View raw message