diff options
-rw-r--r-- | etc/couchdb/default.ini.tpl.in | 5 | ||||
-rw-r--r-- | src/couchdb/couch_httpd.erl | 30 | ||||
-rwxr-xr-x | test/etap/160-vhosts.t | 15 |
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. |