Browse Source

Add cowboy:set_env/3

Loïc Hoguin 12 years ago
parent
commit
b2ffff9bec
5 changed files with 63 additions and 4 deletions
  1. 3 0
      guide/middlewares.md
  2. 14 0
      guide/routing.md
  3. 4 3
      guide/toc.md
  4. 14 0
      src/cowboy.erl
  5. 28 1
      test/http_SUITE.erl

+ 3 - 0
guide/middlewares.md

@@ -58,6 +58,9 @@ will not process any subsequent requests on this connection.
 The middlewares that come with Cowboy may define or require other
 environment values to perform.
 
+You can update the environment by calling the `cowboy:set_env/3`
+convenience function, adding or replacing a value in the environment.
+
 Routing middleware
 ------------------
 

+ 14 - 0
guide/routing.md

@@ -242,3 +242,17 @@ cowboy:start_http(my_http_listener, 100,
 
 Note that this function will return `{error, badarg}` if the structure
 given is incorrect.
+
+Live update
+-----------
+
+You can use the `cowboy:set_env/3` function for updating the dispatch
+list used by routing. This will apply to all new connections accepted
+by the listener.
+
+``` erlang
+cowboy:set_env(my_http_listener, dispatch,
+    cowboy_router:compile(Dispatch)).
+```
+
+Note that you need to compile the routes before updating.

+ 4 - 3
guide/toc.md

@@ -8,10 +8,11 @@ Cowboy User Guide
    *  Getting started
  *  [Routing](routing.md)
    *  Purpose
-   *  Dispatch list
-   *  Match rules
-   *  Bindings
+   *  Structure
+   *  Match syntax
    *  Constraints
+   *  Compilation
+   *  Live update
  *  [Handlers](handlers.md)
    *  Purpose
    *  Protocol upgrades

+ 14 - 0
src/cowboy.erl

@@ -18,6 +18,7 @@
 -export([start_http/4]).
 -export([start_https/4]).
 -export([stop_listener/1]).
+-export([set_env/3]).
 
 %% @doc Start an HTTP listener.
 -spec start_http(any(), non_neg_integer(), any(), any()) -> {ok, pid()}.
@@ -37,3 +38,16 @@ start_https(Ref, NbAcceptors, TransOpts, ProtoOpts)
 -spec stop_listener(any()) -> ok.
 stop_listener(Ref) ->
 	ranch:stop_listener(Ref).
+
+%% @doc Convenience function for setting an environment value.
+%%
+%% Allows you to update live an environment value used by middlewares.
+%% This function is primarily intended to simplify updating the dispatch
+%% list used for routing.
+-spec set_env(any(), atom(), any()) -> ok.
+set_env(Ref, Name, Value) ->
+	Opts = ranch:get_protocol_options(Ref),
+	{_, Env} = lists:keyfind(env, 1, Opts),
+	Env2 = [{Name, Value}|lists:keydelete(Name, 1, Env)],
+	Opts2 = lists:keyreplace(env, 1, Opts, {env, Env2}),
+	ok = ranch:set_protocol_options(Ref, Opts2).

+ 28 - 1
test/http_SUITE.erl

@@ -61,6 +61,7 @@
 -export([rest_patch/1]).
 -export([rest_resource_etags/1]).
 -export([rest_resource_etags_if_none_match/1]).
+-export([set_env_dispatch/1]).
 -export([set_resp_body/1]).
 -export([set_resp_header/1]).
 -export([set_resp_overwrite/1]).
@@ -90,7 +91,8 @@ all() ->
 		{group, https_compress},
 		{group, onrequest},
 		{group, onresponse},
-		{group, onresponse_capitalize}
+		{group, onresponse_capitalize},
+		{group, set_env}
 	].
 
 groups() ->
@@ -159,6 +161,9 @@ groups() ->
 		]},
 		{onresponse_capitalize, [], [
 			onresponse_capitalize
+		]},
+		{set_env, [], [
+			set_env_dispatch
 		]}
 	].
 
@@ -273,6 +278,17 @@ init_per_group(onresponse_capitalize, Config) ->
 	]),
 	{ok, Client} = cowboy_client:init([]),
 	[{scheme, <<"http">>}, {port, Port}, {opts, []},
+		{transport, Transport}, {client, Client}|Config];
+init_per_group(set_env, Config) ->
+	Port = 33087,
+	Transport = ranch_tcp,
+	{ok, _} = cowboy:start_http(set_env, 100, [{port, Port}], [
+		{env, [{dispatch, []}]},
+		{max_keepalive, 50},
+		{timeout, 500}
+	]),
+	{ok, Client} = cowboy_client:init([]),
+	[{scheme, <<"http">>}, {port, Port}, {opts, []},
 		{transport, Transport}, {client, Client}|Config].
 
 end_per_group(Group, Config) when Group =:= https; Group =:= https_compress ->
@@ -923,6 +939,17 @@ rest_resource_etags_if_none_match(Config) ->
 		{Ret, Type}
 	end || {Status, ETag, Type} <- Tests].
 
+set_env_dispatch(Config) ->
+	Client = ?config(client, Config),
+	{ok, Client2} = cowboy_client:request(<<"GET">>,
+		build_url("/", Config), Client),
+	{ok, 400, _, _} = cowboy_client:response(Client2),
+	ok = cowboy:set_env(set_env, dispatch,
+		cowboy_router:compile([{'_', [{"/", http_handler, []}]}])),
+	{ok, Client3} = cowboy_client:request(<<"GET">>,
+		build_url("/", Config), Client),
+	{ok, 200, _, _} = cowboy_client:response(Client3).
+
 set_resp_body(Config) ->
 	Client = ?config(client, Config),
 	{ok, Client2} = cowboy_client:request(<<"GET">>,