summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--etc/couchdb/default.ini.tpl.in5
-rw-r--r--src/couchdb/couch_httpd.erl30
-rwxr-xr-xtest/etap/160-vhosts.t15
3 files changed, 41 insertions, 9 deletions
diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in
index fb88ba63..0222839a 100644
--- a/etc/couchdb/default.ini.tpl.in
+++ b/etc/couchdb/default.ini.tpl.in
@@ -19,6 +19,11 @@ max_connections = 2048
authentication_handlers = {couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}
default_handler = {couch_httpd_db, handle_request}
secure_rewrites = true
+vhost_global_handlers = _utils
+ _uuids
+ _session
+ _oauth
+ _users
[log]
file = %localstatelogdir%/couch.log
diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index f0217a4e..00bfc196 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -13,7 +13,7 @@
-module(couch_httpd).
-include("couch_db.hrl").
--export([start_link/0, stop/0, handle_request/6]).
+-export([start_link/0, stop/0, handle_request/7]).
-export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1,absolute_uri/2,body_length/1]).
-export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,recv_chunked/4,error_info/1]).
@@ -37,7 +37,11 @@ start_link() ->
Port = couch_config:get("httpd", "port", "5984"),
MaxConnections = couch_config:get("httpd", "max_connections", "2048"),
VirtualHosts = couch_config:get("vhosts"),
-
+ VhostGlobals = re:split(
+ couch_config:get("httpd", "vhost_global_handlers", ""),
+ "\\s+",
+ [{return, list}]
+ ),
DefaultSpec = "{couch_httpd_db, handle_request}",
DefaultFun = make_arity_1_fun(
couch_config:get("httpd", "default_handler", DefaultSpec)
@@ -64,7 +68,7 @@ start_link() ->
Loop = fun(Req)->
apply(?MODULE, handle_request, [
Req, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers,
- VirtualHosts
+ VirtualHosts, VhostGlobals
])
end,
@@ -157,19 +161,26 @@ redirect_to_vhost(MochiReq, DefaultFun,
UrlHandlers, DbUrlHandlers, DesignUrlHandlers).
handle_request(MochiReq, DefaultFun,
- UrlHandlers, DbUrlHandlers, DesignUrlHandlers, VirtualHosts) ->
+ UrlHandlers, DbUrlHandlers, DesignUrlHandlers, VirtualHosts, VhostGlobals) ->
% grab Host from Req
Vhost = MochiReq:get_header_value("Host"),
% find Vhost in config
case couch_util:get_value(Vhost, VirtualHosts) of
- undefined -> % business as usual
+ undefined -> % business as usual
+ handle_request_int(MochiReq, DefaultFun,
+ UrlHandlers, DbUrlHandlers, DesignUrlHandlers);
+ VhostTarget ->
+ case vhost_global(VhostGlobals, MochiReq) of
+ true ->% global handler for vhosts
handle_request_int(MochiReq, DefaultFun,
- UrlHandlers, DbUrlHandlers, DesignUrlHandlers);
- VhostTarget ->
+ UrlHandlers, DbUrlHandlers, DesignUrlHandlers);
+ _Else ->
+ % do rewrite
redirect_to_vhost(MochiReq, DefaultFun,
UrlHandlers, DbUrlHandlers, DesignUrlHandlers, VhostTarget)
+ end
end.
@@ -297,6 +308,11 @@ authenticate_request(Response, _AuthSrcs) ->
increment_method_stats(Method) ->
couch_stats_collector:increment({httpd_request_methods, Method}).
+% if so, then it will not be rewritten, but will run as a normal couchdb request.
+% normally you'd use this for _uuids _utils and a few of the others you want to keep available on vhosts. You can also use it to make databases 'global'.
+vhost_global(VhostGlobals, MochiReq) ->
+ "/"++Path = MochiReq:get(path),
+ [true] == [true||V <- VhostGlobals, V == Path].
% Utilities
diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t
index 64c51554..8d8dd2a7 100755
--- a/test/etap/160-vhosts.t
+++ b/test/etap/160-vhosts.t
@@ -54,7 +54,7 @@ config_files() ->
main(_) ->
test_util:init_code_path(),
- etap:plan(3),
+ etap:plan(4),
case (catch test()) of
ok ->
etap:end_tests();
@@ -85,7 +85,8 @@ test() ->
test_regular_request(),
test_vhost_request(),
test_vhost_request_with_qs(),
-
+ test_vhost_request_with_global(),
+
%% restart boilerplate
couch_db:close(Db),
couch_server:delete(list_to_binary(dbname()), []),
@@ -119,3 +120,13 @@ test_vhost_request_with_qs() ->
etap:is(HasRevsInfo, true, "should return _revs_info");
_Else -> false
end.
+
+test_vhost_request_with_global() ->
+ Url = server() ++ "_uuids",
+ case ibrowse:send_req(Url, [], get, [], [{host_header, "example.com"}]) of
+ {ok, _, _, Body} ->
+ {JsonProps} = couch_util:json_decode(Body),
+ HasUuids = proplists:is_defined(<<"uuids">>, JsonProps),
+ etap:is(HasUuids, true, "should return _uuids");
+ _Else -> false
+ end.