couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From beno...@apache.org
Subject svn commit: r986182 - in /couchdb/trunk: etc/couchdb/default.ini.tpl.in src/couchdb/Makefile.am src/couchdb/couch_httpd.erl test/etap/160-vhosts.t
Date Tue, 17 Aug 2010 04:11:02 GMT
Author: benoitc
Date: Tue Aug 17 04:11:02 2010
New Revision: 986182

URL: http://svn.apache.org/viewvc?rev=986182&view=rev
Log:
New vhost manager. allows dynamic add of vhosts without restart,
wildcard in vhost and dynamic routing via pattern matching. Close
#COUCHDB-855.

Modified:
    couchdb/trunk/etc/couchdb/default.ini.tpl.in
    couchdb/trunk/src/couchdb/Makefile.am
    couchdb/trunk/src/couchdb/couch_httpd.erl
    couchdb/trunk/test/etap/160-vhosts.t

Modified: couchdb/trunk/etc/couchdb/default.ini.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/trunk/etc/couchdb/default.ini.tpl.in?rev=986182&r1=986181&r2=986182&view=diff
==============================================================================
--- couchdb/trunk/etc/couchdb/default.ini.tpl.in (original)
+++ couchdb/trunk/etc/couchdb/default.ini.tpl.in Tue Aug 17 04:11:02 2010
@@ -64,6 +64,7 @@ stats_collector={couch_stats_collector, 
 uuids={couch_uuids, start, []}
 auth_cache={couch_auth_cache, start_link, []}
 rep_db_changes_listener={couch_rep_db_listener, start_link, []}
+vhosts={couch_httpd_vhost, start_link, []}
 
 [httpd_global_handlers]
 / = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>}

Modified: couchdb/trunk/src/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/Makefile.am?rev=986182&r1=986181&r2=986182&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/Makefile.am (original)
+++ couchdb/trunk/src/couchdb/Makefile.am Tue Aug 17 04:11:02 2010
@@ -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 \

Modified: couchdb/trunk/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd.erl?rev=986182&r1=986181&r2=986182&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd.erl Tue Aug 17 04:11:02 2010
@@ -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),

Modified: couchdb/trunk/test/etap/160-vhosts.t
URL: http://svn.apache.org/viewvc/couchdb/trunk/test/etap/160-vhosts.t?rev=986182&r1=986181&r2=986182&view=diff
==============================================================================
--- couchdb/trunk/test/etap/160-vhosts.t (original)
+++ couchdb/trunk/test/etap/160-vhosts.t Tue Aug 17 04:11:02 2010
@@ -54,7 +54,7 @@ config_files() ->
 main(_) ->
     test_util:init_code_path(),
 
-    etap:plan(6),
+    etap:plan(10),
     case (catch test()) of
         ok ->
             etap:end_tests();
@@ -69,6 +69,7 @@ test() ->
     ibrowse:start(),
     crypto:start(),
 
+    timer:sleep(1000),
     couch_server:delete(list_to_binary(dbname()), [admin_user_ctx()]),
     {ok, Db} = couch_db:create(list_to_binary(dbname()), [admin_user_ctx()]),
 
@@ -101,9 +102,16 @@ test() ->
 
     %% end boilerplate, start test
 
-    couch_config:set("vhosts", "example.com", "/etap-test-db", false),
-    couch_config:set("vhosts", "example1.com",
-"/etap-test-db/_design/doc1/_rewrite/", false),
+    ok = couch_config:set("vhosts", "example.com", "/etap-test-db", false),
+    ok = couch_config:set("vhosts", "*.example.com", 
+            "/etap-test-db/_design/doc1/_rewrite", false),
+    ok = couch_config:set("vhosts", "example1.com", 
+            "/etap-test-db/_design/doc1/_rewrite/", false),
+    ok = couch_config:set("vhosts","$appname.$dbname.example1.com",
+            "/$dbname/_design/$appname/_rewrite/", false),
+    ok = couch_config:set("vhosts", "$dbname.example1.com", "/$dbname", false),
+    ok = couch_config:set("vhosts", "*.example2.com", "/*", false),
+
 
     test_regular_request(),
     test_vhost_request(),
@@ -111,10 +119,16 @@ test() ->
     test_vhost_request_with_global(),
     test_vhost_requested_path(),    
     test_vhost_requested_path_path(),
+    test_vhost_request_wildcard(),
+    test_vhost_request_replace_var(),
+    test_vhost_request_replace_var1(), 
+    test_vhost_request_replace_wildcard(),
     
     %% restart boilerplate
     couch_db:close(Db),
-    couch_server:delete(list_to_binary(dbname()), []),
+    timer:sleep(3000),
+    couch_server_sup:stop(),    
+
     ok.
 
 test_regular_request() ->
@@ -166,7 +180,6 @@ test_vhost_requested_path() ->
         _Else -> false
     end.
 
-
 test_vhost_requested_path_path() ->
     case ibrowse:send_req(server(), [], get, [], [{host_header, "example1.com"}]) of
         {ok, _, _, Body} ->
@@ -178,3 +191,43 @@ test_vhost_requested_path_path() ->
         _Else -> false
     end.
 
+test_vhost_request_wildcard()->
+    case ibrowse:send_req(server(), [], get, [], [{host_header, "test.example.com"}]) of
+        {ok, _, _, Body} ->
+            {Json} = couch_util:json_decode(Body),
+            etap:is(case proplists:get_value(<<"path">>, Json) of
+                <<"/etap-test-db/_design/doc1/_show/test">> -> true;
+                _ -> false
+            end, true, <<"wildcard  ok">>);
+        _Else -> false
+    end.
+
+
+test_vhost_request_replace_var() ->
+    case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example1.com"}])
of
+        {ok, _, _, Body} ->
+            {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]}
+                = couch_util:json_decode(Body),
+            etap:is(true, true, "should return database info");
+        _Else -> false
+    end.
+
+test_vhost_request_replace_var1() ->
+    case ibrowse:send_req(server(), [], get, [], [{host_header, "doc1.etap-test-db.example1.com"}])
of
+        {ok, _, _, Body} ->
+            {Json} = couch_util:json_decode(Body),
+            etap:is(case proplists:get_value(<<"path">>, Json) of
+                <<"/etap-test-db/_design/doc1/_show/test">> -> true;
+                _ -> false
+            end, true, <<"wildcard  ok">>);
+        _Else -> false
+    end.
+
+test_vhost_request_replace_wildcard() ->
+    case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example2.com"}])
of
+        {ok, _, _, Body} ->
+            {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]}
+                = couch_util:json_decode(Body),
+            etap:is(true, true, "should return database info");
+        _Else -> false
+    end.



Mime
View raw message