You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2015/08/12 17:54:25 UTC
[01/11] chttpd commit: updated refs/heads/master to 238b8c4
Repository: couchdb-chttpd
Updated Branches:
refs/heads/master a66b901e6 -> 238b8c482
Introduce `chttpd_auth:authenticate` hook
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/90f1aa75
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/90f1aa75
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/90f1aa75
Branch: refs/heads/master
Commit: 90f1aa751147f35f823cb33bb53495788c497e05
Parents: a66b901
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Jul 29 09:40:23 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 08:27:51 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 44 +++++++++++++++++++++--------------------
src/chttpd_auth.erl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
src/chttpd_sup.erl | 10 +++++++++-
3 files changed, 83 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 22d0656..b6b30de 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -27,6 +27,8 @@
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]).
+-export([authenticate_request/3]).
+
-export([start_delayed_json_response/2, start_delayed_json_response/3,
start_delayed_json_response/4,
start_delayed_chunked_response/3, start_delayed_chunked_response/4,
@@ -143,11 +145,6 @@ handle_request_int(MochiReq) ->
ok = mochiweb_socket:setopts(MochiReq:get(socket), SocketOpts)
end,
- AuthenticationFuns = [
- fun chttpd_auth:cookie_authentication_handler/1,
- fun chttpd_auth:default_authentication_handler/1
- ],
-
% for the path, use the raw path with the query string and fragment
% removed, but URL quoting left intact
RawUri = MochiReq:get(raw_path),
@@ -215,7 +212,7 @@ handle_request_int(MochiReq) ->
check_request_uri_length(RawUri),
case chttpd_cors:maybe_handle_preflight_request(HttpReq) of
not_preflight ->
- case authenticate_request(HttpReq, AuthenticationFuns) of
+ case chttpd_auth:authenticate(HttpReq, fun authenticate_request/1) of
#httpd{} = Req ->
HandlerFun = chttpd_handlers:url_handler(
HandlerKey, fun chttpd_db:handle_request/1),
@@ -346,28 +343,33 @@ make_uri(Req, Raw) ->
{[{<<"url">>,Url}, {<<"headers">>,{Headers}}]}.
%%% end hack
+authenticate_request(Req) ->
+ AuthenticationFuns = [
+ {<<"cookie">>, fun chttpd_auth:cookie_authentication_handler/1},
+ {<<"default">>, fun chttpd_auth:default_authentication_handler/1},
+ {<<"local">>, fun chttpd_auth:party_mode_handler/1} %% should be last
+ ],
+ authenticate_request(Req, chttpd_auth_cache, AuthenticationFuns).
+
+authenticate_request(#httpd{} = Req0, AuthModule, AuthFuns) ->
+ Req = Req0#httpd{
+ auth_module = AuthModule,
+ authentication_handlers = AuthFuns},
+ authenticate_request(Req, AuthFuns).
% Try authentication handlers in order until one returns a result
authenticate_request(#httpd{user_ctx=#user_ctx{}} = Req, _AuthFuns) ->
Req;
-authenticate_request(#httpd{} = Req, [AuthFun|Rest]) ->
- authenticate_request(AuthFun(Req), Rest);
-authenticate_request(#httpd{} = Req, []) ->
- case config:get("chttpd", "require_valid_user", "false") of
- "true" ->
- throw({unauthorized, <<"Authentication required.">>});
- "false" ->
- case config:get("admins") of
- [] ->
- Ctx = #user_ctx{roles=[<<"_reader">>, <<"_writer">>, <<"_admin">>]},
- Req#httpd{user_ctx = Ctx};
- _ ->
- Req#httpd{user_ctx=#user_ctx{}}
- end
- end;
+authenticate_request(#httpd{} = Req, [{Name, AuthFun}|Rest]) ->
+ authenticate_request(maybe_set_handler(AuthFun(Req), Name), Rest);
authenticate_request(Response, _AuthFuns) ->
Response.
+maybe_set_handler(#httpd{user_ctx=#user_ctx{} = UserCtx} = Req, Name) ->
+ Req#httpd{user_ctx = UserCtx#user_ctx{handler = Name}};
+maybe_set_handler(Else, _) ->
+ Else.
+
increment_method_stats(Method) ->
couch_stats:increment_counter([couchdb, httpd_request_methods, Method]).
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_auth.erl b/src/chttpd_auth.erl
index 1046538..7a45399 100644
--- a/src/chttpd_auth.erl
+++ b/src/chttpd_auth.erl
@@ -12,15 +12,66 @@
-module(chttpd_auth).
+-export([authenticate/2]).
+
-export([default_authentication_handler/1]).
-export([cookie_authentication_handler/1]).
+-export([party_mode_handler/1]).
+
-export([handle_session_req/1]).
+-include_lib("couch/include/couch_db.hrl").
+
+-define(SERVICE_ID, chttpd_auth).
+
+
+%% ------------------------------------------------------------------
+%% API Function Definitions
+%% ------------------------------------------------------------------
+
+authenticate(HttpReq, Default) ->
+ maybe_handle(authenticate, [HttpReq], Default).
+
+
+%% ------------------------------------------------------------------
+%% Default callbacks
+%% ------------------------------------------------------------------
+
default_authentication_handler(Req) ->
couch_httpd_auth:default_authentication_handler(Req, chttpd_auth_cache).
cookie_authentication_handler(Req) ->
couch_httpd_auth:cookie_authentication_handler(Req, chttpd_auth_cache).
+party_mode_handler(Req) ->
+ case config:get("chttpd", "require_valid_user", "false") of
+ "true" ->
+ throw({unauthorized, <<"Authentication required.">>});
+ "false" ->
+ case config:get("admins") of
+ [] ->
+ Ctx = #user_ctx{roles=[<<"_reader">>, <<"_writer">>, <<"_admin">>]},
+ Req#httpd{user_ctx = Ctx};
+ _ ->
+ Req#httpd{user_ctx=#user_ctx{}}
+ end
+ end.
+
handle_session_req(Req) ->
couch_httpd_auth:handle_session_req(Req, chttpd_auth_cache).
+
+
+%% ------------------------------------------------------------------
+%% Internal Function Definitions
+%% ------------------------------------------------------------------
+
+maybe_handle(Func, Args, Default) ->
+ Handle = couch_epi:get_handle(?SERVICE_ID),
+ case couch_epi:apply(Handle, ?SERVICE_ID, Func, Args, [ignore_providers]) of
+ [] when is_function(Default) ->
+ apply(Default, Args);
+ [] ->
+ Default;
+ [Result] ->
+ Result
+ end.
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd_sup.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_sup.erl b/src/chttpd_sup.erl
index a4851e2..62d00eb 100644
--- a/src/chttpd_sup.erl
+++ b/src/chttpd_sup.erl
@@ -26,7 +26,7 @@ init([]) ->
chttpd_config_listener:subscribe(),
{ok, {{one_for_one, 3, 10}, [
?CHILD(chttpd, worker),
- ?CHILD(chttpd_auth_cache, worker),
+ ?CHILD(auth_cache_handler(), worker),
chttpd_handlers:provider(chttpd, chttpd_httpd_handlers),
{chttpd_auth_cache_lru,
{ets_lru, start_link, [chttpd_auth_cache_lru, lru_opts()]},
@@ -52,3 +52,11 @@ lru_opts() ->
_ ->
[]
end.
+
+auth_cache_handler() ->
+ case application:get_env(chttpd, auth_cache) of
+ {ok, Module} ->
+ Module;
+ _ ->
+ chttpd_auth_cache
+ end.
[02/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Use '?ADMIN_USER' for admin party
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/f42f96c8
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/f42f96c8
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/f42f96c8
Branch: refs/heads/master
Commit: f42f96c897a3ad22f40e2c5bf35c737c4fd3fa92
Parents: 90f1aa7
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Aug 5 14:31:31 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 08:44:37 2015 -0700
----------------------------------------------------------------------
src/chttpd_auth.erl | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/f42f96c8/src/chttpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_auth.erl b/src/chttpd_auth.erl
index 7a45399..6683892 100644
--- a/src/chttpd_auth.erl
+++ b/src/chttpd_auth.erl
@@ -50,8 +50,7 @@ party_mode_handler(Req) ->
"false" ->
case config:get("admins") of
[] ->
- Ctx = #user_ctx{roles=[<<"_reader">>, <<"_writer">>, <<"_admin">>]},
- Req#httpd{user_ctx = Ctx};
+ Req#httpd{user_ctx = ?ADMIN_USER};
_ ->
Req#httpd{user_ctx=#user_ctx{}}
end
[04/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Add `chttpd_auth:authorize/2` hook
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/cf58b04e
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/cf58b04e
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/cf58b04e
Branch: refs/heads/master
Commit: cf58b04e96fde0ba012a2aa339f9dc322c2d2f4e
Parents: 8d0fe1c
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Jul 29 10:15:50 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:28 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 4 +++-
src/chttpd_auth.erl | 4 ++++
2 files changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/cf58b04e/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index d1e07e9..215f509 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -220,7 +220,9 @@ handle_request_int(MochiReq) ->
#httpd{} = Req ->
HandlerFun = chttpd_handlers:url_handler(
HandlerKey, fun chttpd_db:handle_request/1),
- HandlerFun(chttpd_auth_request:authorize_request(possibly_hack(Req)));
+ AuthorizedReq = chttpd_auth:authorize(possibly_hack(Req),
+ fun chttpd_auth_request:authorize_request/1),
+ HandlerFun(AuthorizedReq);
Response ->
Response
end;
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/cf58b04e/src/chttpd_auth.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_auth.erl b/src/chttpd_auth.erl
index 6683892..35a4bd5 100644
--- a/src/chttpd_auth.erl
+++ b/src/chttpd_auth.erl
@@ -13,6 +13,7 @@
-module(chttpd_auth).
-export([authenticate/2]).
+-export([authorize/2]).
-export([default_authentication_handler/1]).
-export([cookie_authentication_handler/1]).
@@ -32,6 +33,9 @@
authenticate(HttpReq, Default) ->
maybe_handle(authenticate, [HttpReq], Default).
+authorize(HttpReq, Default) ->
+ maybe_handle(authorize, [HttpReq], Default).
+
%% ------------------------------------------------------------------
%% Default callbacks
[09/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Use `#httpd.qs` field
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/4ba06e0c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/4ba06e0c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/4ba06e0c
Branch: refs/heads/master
Commit: 4ba06e0c290fef1f3324271db9f93f0ca3dee5e6
Parents: b5d65ea
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Fri Jul 31 06:27:20 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/4ba06e0c/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index ec15033..749f550 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -480,8 +480,10 @@ qs_json_value(Req, Key, Default) ->
?JSON_DECODE(Result)
end.
-qs(#httpd{mochi_req=MochiReq}) ->
- MochiReq:parse_qs().
+qs(#httpd{mochi_req = MochiReq, qs = undefined}) ->
+ MochiReq:parse_qs();
+qs(#httpd{qs = QS}) ->
+ QS.
path(#httpd{mochi_req=MochiReq}) ->
MochiReq:get(path).
[07/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Use #httpd.absolute_uri
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/9118f8da
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/9118f8da
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/9118f8da
Branch: refs/heads/master
Commit: 9118f8da1134e6cf5a701e8bbeef270e6c29507b
Parents: 8d8cf91
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Mon Jun 22 11:37:54 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/9118f8da/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 7a7bad9..6a80f05 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -481,7 +481,7 @@ qs(#httpd{mochi_req=MochiReq}) ->
path(#httpd{mochi_req=MochiReq}) ->
MochiReq:get(path).
-absolute_uri(#httpd{mochi_req=MochiReq}, Path) ->
+absolute_uri(#httpd{mochi_req=MochiReq, absolute_uri = undefined}, Path) ->
XHost = config:get("httpd", "x_forwarded_host", "X-Forwarded-Host"),
Host = case MochiReq:get_header_value(XHost) of
undefined ->
@@ -512,7 +512,9 @@ absolute_uri(#httpd{mochi_req=MochiReq}, Path) ->
end
end
end,
- Scheme ++ "://" ++ Host ++ Path.
+ Scheme ++ "://" ++ Host ++ Path;
+absolute_uri(#httpd{absolute_uri = URI}, Path) ->
+ URI ++ Path.
unquote(UrlEncodedString) ->
mochiweb_util:unquote(UrlEncodedString).
[03/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Derive HandlerKey from path_parts
This is a preparation for introducing `before_request` hook.
Plugin might want to manipulate Path in order to affect handler selection.
Therefore HandlerKey calculation has to happen after
`chttpd_plugin:before_request` and it should be based on the value
returned from that call.
HandlerKey was constructed using `mochiweb_util:partition(Path, "/")`.
We change the logic to use first part of path_parts field of #httpd{}
record.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/8d0fe1c7
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/8d0fe1c7
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/8d0fe1c7
Branch: refs/heads/master
Commit: 8d0fe1c7129a27c4b82f2cd3aa2b498bc36dba25
Parents: f42f96c
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Fri Jun 19 14:12:33 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:10:13 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/8d0fe1c7/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index b6b30de..d1e07e9 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -149,8 +149,6 @@ handle_request_int(MochiReq) ->
% removed, but URL quoting left intact
RawUri = MochiReq:get(raw_path),
{"/" ++ Path, _, _} = mochiweb_util:urlsplit_path(RawUri),
- {HandlerKeyStr, _, _} = mochiweb_util:partition(Path, "/"),
- HandlerKey = ?l2b(HandlerKeyStr),
Peer = MochiReq:get(peer),
LogForClosedSocket = io_lib:format("mochiweb_recv_error for ~s - ~p ~s", [
@@ -199,6 +197,12 @@ handle_request_int(MochiReq) ->
|| Part <- string:tokens(Path, "/")]
},
+ HandlerKey =
+ case HttpReq#httpd.path_parts of
+ [] -> <<>>;
+ [Key|_] -> ?l2b(quote(Key))
+ end,
+
% put small token on heap to keep requests synced to backend calls
erlang:put(nonce, couch_util:to_hex(crypto:rand_bytes(5))),
[06/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Refactor handle_request/1 to use #httpd_resp{}
Pass more info into #httpd{} and introduce #httpd_resp{} so we can
abstract updating stats and logging of request into separate functions.
We also prepare for introduction of before_request/after_request hooks.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/8d8cf91a
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/8d8cf91a
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/8d8cf91a
Branch: refs/heads/master
Commit: 8d8cf91a9995a874734873ab767cde46c9c66637
Parents: cf58b04
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Mon Jun 22 05:32:39 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
include/chttpd.hrl | 22 +++++++++++
src/chttpd.erl | 97 ++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 97 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/8d8cf91a/include/chttpd.hrl
----------------------------------------------------------------------
diff --git a/include/chttpd.hrl b/include/chttpd.hrl
new file mode 100644
index 0000000..9d3bd97
--- /dev/null
+++ b/include/chttpd.hrl
@@ -0,0 +1,22 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+
+-record(httpd_resp, {
+ end_ts,
+ code,
+ response,
+ status,
+ nonce,
+ should_log = true,
+ reason
+}).
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/8d8cf91a/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 215f509..7a7bad9 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -12,6 +12,7 @@
-module(chttpd).
-include_lib("couch/include/couch_db.hrl").
+-include_lib("chttpd/include/chttpd.hrl").
-export([start_link/0, start_link/1, start_link/2,
stop/0, handle_request/1, handle_request_int/1,
@@ -190,8 +191,14 @@ handle_request_int(MochiReq) ->
Other -> Other
end,
+ Nonce = couch_util:to_hex(crypto:rand_bytes(5)),
+
HttpReq = #httpd{
mochi_req = MochiReq,
+ begin_ts = Begin,
+ peer = Peer,
+ original_method = Method1,
+ nonce = Nonce,
method = Method,
path_parts = [list_to_binary(chttpd:unquote(Part))
|| Part <- string:tokens(Path, "/")]
@@ -204,12 +211,12 @@ handle_request_int(MochiReq) ->
end,
% put small token on heap to keep requests synced to backend calls
- erlang:put(nonce, couch_util:to_hex(crypto:rand_bytes(5))),
+ erlang:put(nonce, Nonce),
% suppress duplicate log
erlang:put(dont_log_request, true),
- Result =
+ Result0 =
try
couch_httpd:validate_host(HttpReq),
chttpd_csrf:validate(HttpReq),
@@ -260,28 +267,74 @@ handle_request_int(MochiReq) ->
end
end,
- RequestTime = timer:now_diff(os:timestamp(), Begin)/1000,
- {Status, Code} = case Result of
- {ok, #delayed_resp{resp=Resp}} ->
- {ok, Resp:get(code)};
- {ok, Resp} ->
- {ok, Resp:get(code)};
- {aborted, Resp, _} ->
- {aborted, Resp:get(code)}
+ {HttpReq1, HttpResp0} = result(Result0, HttpReq),
+
+ HttpResp1 = update_stats(HttpReq1, HttpResp0),
+ maybe_log(HttpReq1, HttpResp1),
+
+ case HttpResp1 of
+ #httpd_resp{status = ok, response = Resp} ->
+ {ok, Resp};
+ #httpd_resp{status = aborted, reason = Reason} ->
+ couch_log:error("Response abnormally terminated: ~p", [Reason]),
+ exit(normal)
+ end.
+
+result(Result, #httpd{nonce = Nonce} = Req) ->
+ {Status, Code, Reason} = case Result of
+ {ok, #delayed_resp{resp=Resp}} ->
+ {ok, Resp:get(code), undefined};
+ {ok, Resp} ->
+ {ok, Resp:get(code), undefined};
+ {aborted, Resp, AbortReason} ->
+ {aborted, Resp:get(code), AbortReason}
+ end,
+
+ HttpResp = #httpd_resp{
+ code = Code,
+ status = Status,
+ response = Resp,
+ nonce = Nonce,
+ reason = Reason
+ },
+ {Req, HttpResp}.
+
+
+update_stats(HttpReq, #httpd_resp{end_ts = undefined} = Res) ->
+ update_stats(HttpReq, Res#httpd_resp{end_ts = os:timestamp()});
+update_stats(#httpd{begin_ts = BeginTime}, #httpd_resp{} = Res) ->
+ #httpd_resp{status = Status, end_ts = EndTime} = Res,
+ RequestTime = timer:now_diff(EndTime, BeginTime) / 1000,
+ couch_stats:update_histogram([couchdb, request_time], RequestTime),
+ case Status of
+ ok ->
+ couch_stats:increment_counter([couchdb, httpd, requests]);
+ aborted ->
+ couch_stats:increment_counter([couchdb, httpd, aborted_requests])
end,
+ Res.
+
+maybe_log(#httpd{} = HttpReq, #httpd_resp{should_log = true} = HttpResp) ->
+ #httpd{
+ mochi_req = MochiReq,
+ begin_ts = BeginTime,
+ original_method = Method,
+ peer = Peer,
+ nonce = Nonce
+ } = HttpReq,
+ #httpd_resp{
+ end_ts = EndTime,
+ code = Code,
+ status = Status
+ } = HttpResp,
Host = MochiReq:get_header_value("Host"),
- couch_log:notice("~s ~s ~s ~s ~s ~B ~p ~B", [get(nonce), Peer, Host,
- atom_to_list(Method1), RawUri, Code, Status, round(RequestTime)]),
- couch_stats:update_histogram([couchdb, request_time], RequestTime),
- case Result of
- {ok, _} ->
- couch_stats:increment_counter([couchdb, httpd, requests]),
- {ok, Resp};
- {aborted, _, Reason} ->
- couch_stats:increment_counter([couchdb, httpd, aborted_requests]),
- couch_log:error("Response abnormally terminated: ~p", [Reason]),
- exit(normal)
- end.
+ RawUri = MochiReq:get(raw_path),
+ RequestTime = timer:now_diff(EndTime, BeginTime) / 1000,
+ couch_log:notice("~s ~s ~s ~s ~s ~B ~p ~B", [Nonce, Peer, Host,
+ atom_to_list(Method), RawUri, Code, Status, round(RequestTime)]);
+maybe_log(_HttpReq, #httpd_resp{should_log = false}) ->
+ ok.
+
%% HACK: replication currently handles two forms of input, #db{} style
%% and #http_db style. We need a third that makes use of fabric. #db{}
[05/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Use private to_lower instead of string:to_lower
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/b5d65eae
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/b5d65eae
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/b5d65eae
Branch: refs/heads/master
Commit: b5d65eaef90435f1041b8d697788d3825e540b03
Parents: 64aa2fd
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Jul 29 11:59:42 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd_cors.erl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/b5d65eae/src/chttpd_cors.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_cors.erl b/src/chttpd_cors.erl
index fc30c9a..525fc5f 100644
--- a/src/chttpd_cors.erl
+++ b/src/chttpd_cors.erl
@@ -130,7 +130,7 @@ handle_preflight_request(Req, Config, Origin) ->
%% transform header list in something we
%% could check. make sure everything is a
%% list
- RH = [string:to_lower(H)
+ RH = [to_lower(H)
|| H <- split_headers(Headers)],
{Headers, RH}
end,
@@ -346,7 +346,7 @@ get_origin(Req) ->
undefined ->
undefined;
Origin ->
- list_to_binary(string:to_lower(Origin))
+ ?l2b(to_lower(Origin))
end.
[10/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Use `#httpd.cors_config`
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/2b427592
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/2b427592
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/2b427592
Branch: refs/heads/master
Commit: 2b427592d811db38723905127157a06bb3a19a9d
Parents: 9118f8d
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Mon Jun 29 06:19:11 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd_cors.erl | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/2b427592/src/chttpd_cors.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_cors.erl b/src/chttpd_cors.erl
index cedb86e..fc30c9a 100644
--- a/src/chttpd_cors.erl
+++ b/src/chttpd_cors.erl
@@ -265,7 +265,7 @@ allow_credentials(Config, Origin) ->
get_origin_config(Config, Origin, <<"allow_credentials">>,
?CORS_DEFAULT_ALLOW_CREDENTIALS).
-get_cors_config(_Req) ->
+get_cors_config(#httpd{cors_config = undefined}) ->
EnableCors = config:get("httpd", "enable_cors", "false") =:= "true",
AllowCredentials = config:get("cors", "credentials", "false") =:= "true",
AllowHeaders = case config:get("cors", "methods", undefined) of
@@ -288,8 +288,9 @@ get_cors_config(_Req) ->
{<<"allow_methods">>, AllowMethods},
{<<"allow_headers">>, AllowHeaders},
{<<"origins">>, {Origins}}
- ].
-
+ ];
+get_cors_config(#httpd{cors_config = Config}) ->
+ Config.
is_cors_enabled(Config) ->
case get(disable_couch_httpd_cors) of
[11/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Return `{error, {illegal_database_name, Name}}`
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/238b8c48
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/238b8c48
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/238b8c48
Branch: refs/heads/master
Commit: 238b8c48285ed118821807ee057d1a59775acb06
Parents: 4ba06e0
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Fri Jul 31 11:35:24 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 9 +++++----
test/chttpd_error_info_tests.erl | 6 +++---
2 files changed, 8 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/238b8c48/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 749f550..52400ca 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -804,10 +804,11 @@ error_info({bad_ctype, Reason}) ->
{415, <<"bad_content_type">>, Reason};
error_info(requested_range_not_satisfiable) ->
{416, <<"requested_range_not_satisfiable">>, <<"Requested range not satisfiable">>};
-error_info({error, illegal_database_name}) ->
- {400, <<"illegal_database_name">>, <<"Only lowercase letters (a-z), "
- "digits (0-9), and any of the characters _, $, (, ), +, -, and / are "
- "allowed. Moreover, the database name must begin with a letter.">>};
+error_info({error, {illegal_database_name, Name}}) ->
+ Message = <<"Name: '", Name/binary, "'. Only lowercase characters (a-z), ",
+ "digits (0-9), and any of the characters _, $, (, ), +, -, and / ",
+ "are allowed. Must begin with a letter.">>,
+ {400, <<"illegal_database_name">>, Message};
error_info({missing_stub, Reason}) ->
{412, <<"missing_stub">>, Reason};
error_info(request_entity_too_large) ->
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/238b8c48/test/chttpd_error_info_tests.erl
----------------------------------------------------------------------
diff --git a/test/chttpd_error_info_tests.erl b/test/chttpd_error_info_tests.erl
index 447eb42..cb0a58a 100644
--- a/test/chttpd_error_info_tests.erl
+++ b/test/chttpd_error_info_tests.erl
@@ -110,11 +110,11 @@ error_info_test() ->
<<"Requested range not satisfiable">>}
},
{
- {error, illegal_database_name},
+ {error, {illegal_database_name, <<"foo">>}},
{400, <<"illegal_database_name">>,
- <<"Only lowercase letters (a-z), digits (0-9), and any of"
+ <<"Name: 'foo'. Only lowercase characters (a-z), digits (0-9), and any of"
" the characters _, $, (, ), +, -, and / are allowed."
- " Moreover, the database name must begin with a letter.">>}
+ " Must begin with a letter.">>}
},
{
{missing_stub, Reason},
[08/11] chttpd commit: updated refs/heads/master to 238b8c4
Posted by rn...@apache.org.
Add chttpd_plugin hooks
We add following hooks:
- chttpd_plugin:before_request/1
- chttpd_plugin:after_request/2
- chttpd_plugin:handle_error/1
Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/64aa2fd0
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/64aa2fd0
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/64aa2fd0
Branch: refs/heads/master
Commit: 64aa2fd0933f1ac8beb3584441663b20cf6e3179
Parents: 2b42759
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Jul 29 11:31:28 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Tue Aug 11 09:14:29 2015 -0700
----------------------------------------------------------------------
src/chttpd.erl | 32 +++++++++++++++++++++++--------
src/chttpd_plugin.erl | 48 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/64aa2fd0/src/chttpd.erl
----------------------------------------------------------------------
diff --git a/src/chttpd.erl b/src/chttpd.erl
index 6a80f05..ec15033 100644
--- a/src/chttpd.erl
+++ b/src/chttpd.erl
@@ -193,7 +193,7 @@ handle_request_int(MochiReq) ->
Nonce = couch_util:to_hex(crypto:rand_bytes(5)),
- HttpReq = #httpd{
+ HttpReq0 = #httpd{
mochi_req = MochiReq,
begin_ts = Begin,
peer = Peer,
@@ -204,6 +204,8 @@ handle_request_int(MochiReq) ->
|| Part <- string:tokens(Path, "/")]
},
+ {ok, HttpReq} = chttpd_plugin:before_request(HttpReq0),
+
HandlerKey =
case HttpReq#httpd.path_parts of
[] -> <<>>;
@@ -229,7 +231,7 @@ handle_request_int(MochiReq) ->
HandlerKey, fun chttpd_db:handle_request/1),
AuthorizedReq = chttpd_auth:authorize(possibly_hack(Req),
fun chttpd_auth_request:authorize_request/1),
- HandlerFun(AuthorizedReq);
+ {AuthorizedReq, HandlerFun(AuthorizedReq)};
Response ->
Response
end;
@@ -268,11 +270,12 @@ handle_request_int(MochiReq) ->
end,
{HttpReq1, HttpResp0} = result(Result0, HttpReq),
+ {ok, HttpResp1} = chttpd_plugin:after_request(HttpReq1, HttpResp0),
- HttpResp1 = update_stats(HttpReq1, HttpResp0),
- maybe_log(HttpReq1, HttpResp1),
+ HttpResp2 = update_stats(HttpReq1, HttpResp1),
+ maybe_log(HttpReq1, HttpResp2),
- case HttpResp1 of
+ case HttpResp2 of
#httpd_resp{status = ok, response = Resp} ->
{ok, Resp};
#httpd_resp{status = aborted, reason = Reason} ->
@@ -280,6 +283,8 @@ handle_request_int(MochiReq) ->
exit(normal)
end.
+result({#httpd{} = Req, Result}, _) ->
+ result(Result, Req);
result(Result, #httpd{nonce = Nonce} = Req) ->
{Status, Code, Reason} = case Result of
{ok, #delayed_resp{resp=Resp}} ->
@@ -817,14 +822,25 @@ error_info({timeout, _Reason}) ->
error_info(timeout);
error_info({Error, null}) ->
error_info(Error);
-error_info({Error, Reason}) ->
- {500, couch_util:to_binary(Error), couch_util:to_binary(Reason)};
+error_info({_Error, _Reason} = Error) ->
+ maybe_handle_error(Error);
error_info({Error, nil, _Stack}) ->
error_info(Error);
error_info({Error, Reason, _Stack}) ->
{500, couch_util:to_binary(Error), couch_util:to_binary(Reason)};
error_info(Error) ->
- {500, <<"unknown_error">>, couch_util:to_binary(Error)}.
+ maybe_handle_error({<<"unknown_error">>, Error}).
+
+maybe_handle_error(Error) ->
+ case chttpd_plugin:handle_error(Error) of
+ {_Code, _Reason, _Description} = Result ->
+ Result;
+ {Err, Reason} ->
+ {500, couch_util:to_binary(Err), couch_util:to_binary(Reason)};
+ Error ->
+ {500, couch_util:to_binary(Error), null}
+ end.
+
error_headers(#httpd{mochi_req=MochiReq}=Req, 401=Code, ErrorStr, ReasonStr) ->
% this is where the basic auth popup is triggered
http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/64aa2fd0/src/chttpd_plugin.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_plugin.erl b/src/chttpd_plugin.erl
new file mode 100644
index 0000000..e174a68
--- /dev/null
+++ b/src/chttpd_plugin.erl
@@ -0,0 +1,48 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_plugin).
+
+-export([
+ before_request/1,
+ after_request/2,
+ handle_error/1
+]).
+
+-include_lib("couch/include/couch_db.hrl").
+
+%% ------------------------------------------------------------------
+%% API Function Definitions
+%% ------------------------------------------------------------------
+
+before_request(HttpReq) ->
+ [HttpReq1] = with_pipe(before_request, [HttpReq]),
+ {ok, HttpReq1}.
+
+after_request(HttpReq, Result) ->
+ [_, Result1] = with_pipe(after_request, [HttpReq, Result]),
+ {ok, Result1}.
+
+handle_error(Error) ->
+ [Error1] = with_pipe(after_request, [Error]),
+ Error1.
+
+%% ------------------------------------------------------------------
+%% Internal Function Definitions
+%% ------------------------------------------------------------------
+
+with_pipe(Func, Args) ->
+ do_apply(Func, Args, [ignore_providers, pipe]).
+
+do_apply(Func, Args, Opts) ->
+ Handle = couch_epi:get_handle(chttpd),
+ couch_epi:apply(Handle, chttpd, Func, Args, Opts).