Browse Source

Make Cowboy an OTP application again, properly this time.

As requested by many people on IRC Cowboy is now a proper OTP application
to support soft code upgrades. It should also be easier to start and stop
listeners now using cowboy:start_listener/6 and cowboy:stop_listener/1.
Loïc Hoguin 14 years ago
parent
commit
718baffa3c
5 changed files with 115 additions and 20 deletions
  1. 16 19
      README.md
  2. 3 1
      src/cowboy.app.src
  3. 33 0
      src/cowboy.erl
  4. 30 0
      src/cowboy_app.erl
  5. 33 0
      src/cowboy_sup.erl

+ 16 - 19
README.md

@@ -33,8 +33,8 @@ Embedding Cowboy
 Getting Started
 ---------------
 
-Cowboy provides an anonymous listener supervisor that you can directly embed
-in your application's supervision tree.
+Cowboy can be started and stopped like any other application. However, the
+Cowboy application do not start any listener, those must be started manually.
 
 A listener is a special kind of supervisor that handles a pool of acceptor
 processes. It also manages all its associated request processes. This allows
@@ -48,25 +48,22 @@ before you can start a listener supervisor.
 For HTTP applications the transport can be either TCP or SSL for HTTP and
 HTTPS respectively. On the other hand, the protocol is of course HTTP.
 
+You can start and stop listeners by calling cowboy:start_listener and
+cowboy:stop_listener respectively. It is your responsability to give each
+listener a unique name.
+
 Code speaks more than words:
 
-    -module(my_app).
-    -behaviour(application).
-    -export([start/2, stop/1]).
-
-    start(_Type, _Args) ->
-        Dispatch = [
-            %% {Host, list({Path, Handler, Opts})}
-            {'_', [{'_', my_handler, []}]}
-        ],
-        %% NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
-        cowboy_listener_sup:start_link(100,
-            cowboy_tcp_transport, [{port, 8080}],
-            cowboy_http_protocol, [{dispatch, Dispatch}]
-        ).
-
-    stop(_State) ->
-        ok.
+    application:start(cowboy),
+    Dispatch = [
+        %% {Host, list({Path, Handler, Opts})}
+        {'_', [{'_', my_handler, []}]}
+    ],
+    %% Name, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
+    cowboy:start_listener(http, 100,
+        cowboy_tcp_transport, [{port, 8080}],
+        cowboy_http_protocol, [{dispatch, Dispatch}]
+    ).
 
 You must also write the `my_handler` module to process requests. You can
 use one of the predefined handlers or write your own. An hello world HTTP

+ 3 - 1
src/cowboy.app.src

@@ -20,5 +20,7 @@
 	{applications, [
 		kernel,
 		stdlib
-	]}
+	]},
+	{mod, {cowboy_app, []}},
+	{env, []}
 ]}.

+ 33 - 0
src/cowboy.erl

@@ -0,0 +1,33 @@
+%% Copyright (c) 2011, Loïc Hoguin <essen@dev-extend.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(cowboy).
+-export([start_listener/6, stop_listener/1]). %% API.
+
+%% API.
+
+-spec start_listener(Ref::term(), NbAcceptors::non_neg_integer(),
+	Transport::module(), TransOpts::term(), Protocol::module(),
+	ProtoOpts::term()) -> {ok, Pid::pid()}.
+start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) ->
+	supervisor:start_child(cowboy_sup,
+		{{cowboy_listener_sup, Ref}, {cowboy_listener_sup, start_link, [
+			NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
+		]},
+		permanent, 5000, supervisor, [cowboy_listener_sup]}).
+
+-spec stop_listener(Ref::term()) -> ok.
+stop_listener(Ref) ->
+	supervisor:terminate_child(cowboy_sup, {cowboy_listener_sup, Ref}),
+	supervisor:delete_child(cowboy_sup, {cowboy_listener_sup, Ref}).

+ 30 - 0
src/cowboy_app.erl

@@ -0,0 +1,30 @@
+%% Copyright (c) 2011, Loïc Hoguin <essen@dev-extend.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(cowboy_app).
+-behaviour(application).
+
+-export([start/2, stop/1]). %% API.
+
+-include("include/types.hrl").
+
+%% API.
+
+-spec start(Type::application_start_type(), Args::term()) -> {ok, Pid::pid()}.
+start(_Type, _Args) ->
+	cowboy_sup:start_link().
+
+-spec stop(State::term()) -> ok.
+stop(_State) ->
+	ok.

+ 33 - 0
src/cowboy_sup.erl

@@ -0,0 +1,33 @@
+%% Copyright (c) 2011, Loïc Hoguin <essen@dev-extend.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(cowboy_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]). %% API.
+-export([init/1]). %% supervisor.
+
+-define(SUPERVISOR, ?MODULE).
+
+%% API.
+
+-spec start_link() -> {ok, Pid::pid()}.
+start_link() ->
+	supervisor:start_link({local, ?SUPERVISOR}, ?MODULE, []).
+
+%% supervisor.
+
+-spec init([]) -> term(). %% @todo These specs should be improved.
+init([]) ->
+	{ok, {{one_for_one, 10, 10}, []}}.