From 84ad2322c28a4d40463dbe031ee0778d50d6b18a Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Tue, 17 Aug 2010 04:11:02 +0000 Subject: New vhost manager. allows dynamic add of vhosts without restart, wildcard in vhost and dynamic routing via pattern matching. Close #COUCHDB-855. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@986182 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/Makefile.am | 2 ++ src/couchdb/couch_httpd.erl | 76 +++++---------------------------------------- 2 files changed, 10 insertions(+), 68 deletions(-) (limited to 'src/couchdb') diff --git a/src/couchdb/Makefile.am b/src/couchdb/Makefile.am index 219f7d82..badfb104 100644 --- a/src/couchdb/Makefile.am +++ b/src/couchdb/Makefile.am @@ -52,6 +52,7 @@ source_files = \ couch_httpd_misc_handlers.erl \ couch_httpd_rewrite.erl \ couch_httpd_stats_handlers.erl \ + couch_httpd_vhost.erl \ couch_key_tree.erl \ couch_log.erl \ couch_native_process.erl \ @@ -111,6 +112,7 @@ compiled_files = \ couch_httpd_misc_handlers.beam \ couch_httpd_rewrite.beam \ couch_httpd_stats_handlers.beam \ + couch_httpd_vhost.beam \ couch_key_tree.beam \ couch_log.beam \ couch_native_process.beam \ diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index b5fe6cce..ecb4421d 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, start_link/1, stop/0, handle_request/7]). +-export([start_link/0, start_link/1, stop/0, handle_request/5]). -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]). @@ -26,6 +26,7 @@ -export([send_response/4,send_method_not_allowed/2,send_error/4, send_redirect/2,send_chunked_error/2]). -export([send_json/2,send_json/3,send_json/4,last_chunk/1,parse_multipart_request/3]). -export([accepted_encodings/1,handle_request_int/5,validate_referer/1,validate_ctype/2]). +-export([make_arity_1_fun/1, make_arity_2_fun/1, make_arity_3_fun/1]). start_link() -> start_link(http). @@ -56,12 +57,7 @@ start_link(Name, Options) -> BindAddress = couch_config:get("httpd", "bind_address", any), %% MaxConnections = couch_config:get("httpd", "max_connections", "2048"), - VirtualHosts = couch_config:get("vhosts"), - VhostGlobals = re:split( - couch_config:get("httpd", "vhost_global_handlers", ""), - ", ?", - [{return, list}] - ), + DefaultSpec = "{couch_httpd_db, handle_request}", DefaultFun = make_arity_1_fun( couch_config:get("httpd", "default_handler", DefaultSpec) @@ -87,8 +83,7 @@ start_link(Name, Options) -> DesignUrlHandlers = dict:from_list(DesignUrlHandlersList), Loop = fun(Req)-> apply(?MODULE, handle_request, [ - Req, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers, - VirtualHosts, VhostGlobals + Req, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers ]) end, @@ -159,54 +154,13 @@ make_fun_spec_strs(SpecStr) -> stop() -> mochiweb_http:stop(?MODULE). -%% -% if there's a vhost definition that matches the request, redirect internally -redirect_to_vhost(MochiReq, DefaultFun, - UrlHandlers, DbUrlHandlers, DesignUrlHandlers, VhostTarget) -> - - Path = MochiReq:get(raw_path), - Target = VhostTarget ++ Path, - ?LOG_DEBUG("Vhost Target: '~p'~n", [Target]), - - Headers = mochiweb_headers:enter("x-couchdb-vhost-path", Path, - MochiReq:get(headers)), - - % build a new mochiweb request - MochiReq1 = mochiweb_request:new(MochiReq:get(socket), - MochiReq:get(method), - Target, - MochiReq:get(version), - Headers), - % cleanup, It force mochiweb to reparse raw uri. - MochiReq1:cleanup(), +handle_request(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers, + DesignUrlHandlers) -> + MochiReq1 = couch_httpd_vhost:match_vhost(MochiReq), handle_request_int(MochiReq1, DefaultFun, - UrlHandlers, DbUrlHandlers, DesignUrlHandlers). - -handle_request(MochiReq, DefaultFun, - 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 - 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); - _Else -> - % do rewrite - redirect_to_vhost(MochiReq, DefaultFun, - UrlHandlers, DbUrlHandlers, DesignUrlHandlers, VhostTarget) - end - end. - + UrlHandlers, DbUrlHandlers, DesignUrlHandlers). handle_request_int(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers) -> @@ -273,8 +227,6 @@ handle_request_int(MochiReq, DefaultFun, Other -> Other end, - - HttpReq = #httpd{ mochi_req = MochiReq, peer = MochiReq:get(peer), @@ -362,18 +314,6 @@ 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), - Front = case partition(Path) of - {"", "", ""} -> - "/"; % Special case the root url handler - {FirstPart, _, _} -> - FirstPart - end, - [true] == [true||V <- VhostGlobals, V == Front]. - validate_referer(Req) -> Host = host_for_request(Req), Referer = header_value(Req, "Referer", fail), -- cgit v1.2.3