Browse Source

Update the Getting started chapter to new erlang.mk

Length of the chapter divided by 2! \o/
Loïc Hoguin 10 years ago
parent
commit
8d436c4744
1 changed files with 106 additions and 243 deletions
  1. 106 243
      doc/src/guide/getting_started.ezdoc

+ 106 - 243
doc/src/guide/getting_started.ezdoc

@@ -12,295 +12,158 @@ Cowboy, writing your first application and generating your first
 release. At the end of this chapter you should know everything
 release. At the end of this chapter you should know everything
 you need to push your first Cowboy application to production.
 you need to push your first Cowboy application to production.
 
 
-:: Application skeleton
+:: Bootstrap
 
 
-Let's start by creating this application. We will simply call it
-`hello_erlang`. This application will have the following directory
-structure:
+We are going to use the ^"erlang.mk^https://github.com/extend/erlang.mk
+build system. It also offers bootstrap features allowing us to
+quickly get started without having to deal with minute details.
 
 
-``` bash
-hello_erlang/
-    src/
-        hello_erlang.app.src
-        hello_erlang_app.erl
-        hello_erlang_sup.erl
-        hello_handler.erl
-    erlang.mk
-    Makefile
-    relx.config
-```
-
-Once the release is generated, we will also have the following
-files added:
-
-``` bash
-hello_erlang/
-    ebin/
-        hello_erlang.app
-        hello_erlang_app.beam
-        hello_erlang_sup.beam
-        hello_handler.beam
-    _rel/
-    relx
-```
-
-As you can probably guess, the `.app.src` file end up becoming
-the `.app` file, and the `.erl` files are compiled into `.beam`.
-Then, the whole release will be copied into the `_rel/` directory.
-
-The `.app` file contains various informations about the application.
-It contains its name, a description, a version, a list of modules,
-default configuration and more.
-
-Using a build system like ^"erlang.mk^https://github.com/extend/erlang.mk^,
-the list of modules will be included automatically in the `.app` file,
-so you don't need to manually put them in your `.app.src` file.
-
-For generating the release, we will use ^"relx^https://github.com/erlware/relx
-as it is a much simpler alternative to the tool coming with Erlang.
-
-First, create the `hello_erlang` directory. It should have the same name
-as the application within it. Then we create the `src` directory inside
-it, which will contain the source code for our application.
+First, let's create the directory for our application.
 
 
 ``` bash
 ``` bash
 $ mkdir hello_erlang
 $ mkdir hello_erlang
 $ cd hello_erlang
 $ cd hello_erlang
-$ mkdir src
 ```
 ```
 
 
-Let's first create the `hello_erlang.app.src` file. It should be pretty
-straightforward for the most part. You can use the following template
-and change what you like in it.
+Then we need to download `erlang.mk`. Either use the following
+command or download it manually.
 
 
-``` erlang
-{application, hello_erlang, [
-    {description, "Hello world with Cowboy!"},
-    {vsn, "0.1.0"},
-    {modules, []},
-    {registered, [hello_erlang_sup]},
-    {applications, [
-        kernel,
-        stdlib,
-        cowboy
-    ]},
-    {mod, {hello_erlang_app, []}},
-    {env, []}
-]}.
+``` bash
+$ wget https://raw.githubusercontent.com/extend/erlang.mk/master/erlang.mk
 ```
 ```
 
 
-The `modules` line will be replaced with the list of modules during
-compilation. Make sure to leave this line even if you do not use it
-directly.
-
-The `registered` value indicates which processes are registered by this
-application. You will often only register the top-level supervisor
-of the application.
-
-The `applications` value lists the applications that must be started
-for this application to work. The Erlang release will start all the
-applications listed here automatically.
+We can now bootstrap our application. Since we are going to generate
+a release, we will also bootstrap it at the same time.
 
 
-The `mod` value defines how the application should be started. Erlang
-will use the `hello_erlang_app` module for starting the application.
-
-The `hello_erlang_app` module is what we call an application behavior.
-The application behavior must define two functions: `start/2` and
-`stop/1`, for starting and stopping the application. A typical
-application module would look like this:
-
-``` erlang
--module(hello_erlang_app).
--behavior(application).
-
--export([start/2]).
--export([stop/1]).
+``` bash
+$ make -f erlang.mk bootstrap bootstrap-rel
+```
 
 
-start(_Type, _Args) ->
-    hello_erlang_sup:start_link().
+This creates a Makefile, a base application, and the release files
+necessary for creating the release. We can already build and start
+this release.
 
 
-stop(_State) ->
-    ok.
+``` bash
+$ make
+...
+$ ./_rel/hello_erlang_release/bin/hello_erlang_release console
+...
+(hello_erlang@127.0.0.1)1>
 ```
 ```
 
 
-That's not enough however. Since we are building a Cowboy based
-application, we also need to initialize Cowboy when we start our
+Entering the command `i().` will show the running processes, including
+one called `hello_erlang_sup`. This is the supervisor for our
 application.
 application.
 
 
-:: Setting up Cowboy
+The release currently does nothing. In the rest of this chapter we
+will add Cowboy as a dependency and write a simple "Hello world!"
+handler.
 
 
-Cowboy does nothing by default.
+:: Cowboy setup
 
 
-Cowboy uses Ranch for handling the connections and provides convenience
-functions to start Ranch listeners.
+To add Cowboy as a dependency of your application, we need to modify
+two files: the Makefile and the application resource file.
 
 
-The `cowboy:start_http/4` function starts a listener for HTTP connections
-using the TCP transport. The `cowboy:start_https/4` function starts a
-listener for HTTPS connections using the SSL transport.
+Modifying the Makefile allows the build system to know it needs to
+fetch and compile Cowboy. To do that we simply need to add one line
+to our Makefile to make it look like this:
 
 
-Listeners are a group of processes that are used to accept and manage
-connections. The processes used specifically for accepting connections
-are called acceptors. The number of acceptor processes is unrelated to
-the maximum number of connections Cowboy can handle. Please refer to
-the ^"Ranch guide^http://ninenines.eu/docs/en/ranch/HEAD/guide/
-for in-depth information.
-
-Listeners are named. They spawn a given number of acceptors, listen for
-connections using the given transport options and pass along the protocol
-options to the connection processes. The protocol options must include
-the dispatch list for routing requests to handlers.
-
-The dispatch list is explained in greater details in the
-^"Routing^routing^ chapter. For the purpose of this example
-we will simply map all URLs to our handler `hello_handler`,
-using the wildcard `_` for both the hostname and path parts
-of the URL.
-
-This is what the `hello_erlang_app:start/2` function looks like
-with Cowboy initialized.
-
-``` erlang
-start(_Type, _Args) ->
-    Dispatch = cowboy_router:compile([
-        %% {URIHost, list({URIPath, Handler, Opts})}
-        {'_', [{'_', hello_handler, []}]}
-    ]),
-    %% Name, NbAcceptors, TransOpts, ProtoOpts
-    cowboy:start_http(my_http_listener, 100,
-        [{port, 8080}],
-        [{env, [{dispatch, Dispatch}]}]
-    ),
-    hello_erlang_sup:start_link().
+``` Makefile
+PROJECT = hello_erlang
+DEPS = cowboy
+include erlang.mk
 ```
 ```
 
 
-Do note that we told Cowboy to start listening on port 8080.
-You can change this value if needed.
+Modifying the application resource file, `src/hello_erlang.app.src`,
+allows the build system to know it needs to include Cowboy in the
+release and start it automatically. This is a different step because
+some dependencies are only needed during development.
 
 
-Our application doesn't need to start any process, as Cowboy
-will automatically start processes for every incoming
-connections. We are still required to have a top-level supervisor
-however, albeit a fairly small one.
+We are simply going to add `cowboy` to the list of `applications`,
+right after `stdlib`. Don't forget the comma separator.
 
 
 ``` erlang
 ``` erlang
--module(hello_erlang_sup).
--behavior(supervisor).
-
--export([start_link/0]).
--export([init/1]).
-
-start_link() ->
-    supervisor:start_link({local, ?MODULE}, ?MODULE, []).
-
-init([]) ->
-    {ok, {{one_for_one, 10, 10}, []}}.
+{application, hello_erlang, [
+	{description, "Hello Erlang!"},
+	{vsn, "0.1.0"},
+	{modules, []},
+	{registered, []},
+	{applications, [
+		kernel,
+		stdlib,
+		cowboy
+	]},
+	{mod, {hello_erlang_app, []}},
+	{env, []}
+]}.
 ```
 ```
 
 
-Finally, we need to write the code for handling incoming requests.
-
-:: Handling HTTP requests
-
-Cowboy features many kinds of handlers. For this simple example,
-we will just use the plain HTTP handler, which has three callback
-functions: `init/3`, `handle/2` and `terminate/3`. You can find more
-information about the arguments and possible return values of these
-callbacks in the
-^"cowboy_http_handler function reference^http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_http_handler^.
-
-Our handler will only send a friendly hello back to the client.
-
-``` erlang
--module(hello_handler).
--behavior(cowboy_http_handler).
-
--export([init/3]).
--export([handle/2]).
--export([terminate/3]).
-
-init(_Type, Req, _Opts) ->
-    {ok, Req, undefined_state}.
-
-handle(Req, State) ->
-    {ok, Req2} = cowboy_req:reply(200, [
-        {<<"content-type">>, <<"text/plain">>}
-    ], <<"Hello World!">>, Req),
-    {ok, Req2, State}.
-
-terminate(_Reason, _Req, _State) ->
-    ok.
-```
+You may want to set a description for the application while you
+are editing the file.
 
 
-The `Req` variable above is the Req object, which allows the developer
-to obtain information about the request and to perform a reply.
-Its usage is documented in the
-^"cowboy_req function reference^http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_req^.
+If you run `make` now and start the release, Cowboy will be included
+and started automatically. This is not enough however, as Cowboy
+doesn't do anything by default. We still need to tell Cowboy to
+listen for connections.
 
 
-The code for our application is ready, so let's build a release!
+:: Listening for connections
 
 
-:: Compiling
+We will do this when our application starts. It's a two step process.
+First we need to define and compile the dispatch list, a list of
+routes that Cowboy will use to map requests to handler modules.
+Then we tell Cowboy to listen for connections.
 
 
-First we need to download `erlang.mk`.
+Open the `src/hello_erlang_app.erl` file and add the necessary
+code to the `start/2` function to make it look like this:
 
 
-``` bash
-$ wget https://raw.github.com/extend/erlang.mk/master/erlang.mk
-$ ls
-src/
-erlang.mk
+``` erlang
+start(_Type, _Args) ->
+	Dispatch = cowboy_router:compile([
+		{'_', [{"/", hello_handler, []}]}
+	]),
+	cowboy:start_http(my_http_listener, 100, [{port, 8080}],
+		[{env, [{dispatch, Dispatch}]}]
+	),
+	hello_erlang_sup:start_link().
 ```
 ```
 
 
-Then we need to create a Makefile that will include `erlang.mk`
-for building our application. We need to define the Cowboy
-dependency in the Makefile. Thankfully `erlang.mk` already
-knows where to find Cowboy as it features a package index,
-so we can just tell it to look there.
+The dispatch list is explained in great details in the
+^"Routing^routing^ chapter. For this tutorial we map the
+path `/` to the handler module `hello_handler`. This module
+doesn't exist yet, we still have to write it.
 
 
-``` Makefile
-PROJECT = hello_erlang
+If you build the release, start it and open ^http://localhost:8080
+now, you will get an error because the module is missing. Any
+other URL, like ^http://localhost:8080/test^, will result in a
+404 error.
 
 
-DEPS = cowboy
-dep_cowboy = pkg://cowboy master
-
-include erlang.mk
-```
+:: Handling requests
 
 
-Note that when creating production nodes you will most likely
-want to use a specific version of Cowboy instead of `master`,
-and properly test your release every time you update Cowboy.
+Cowboy features different kinds of handlers, including REST
+and Websocket handlers. For this tutorial we will use a plain
+HTTP handler.
 
 
-If you type `make` in a shell now, your application should build
-as expected. If you get compilation errors, double check that you
-haven't made any typo when creating the previous files.
+First, let's generate a handler from a template.
 
 
 ``` bash
 ``` bash
-$ make
+$ make new t=cowboy_http n=hello_handler
 ```
 ```
 
 
-:: Generating the release
-
-That's not all however, as we want to create a working release.
-For that purpose, we need to create a `relx.config` file. When
-this file exists, `erlang.mk` will automatically download `relx`
-and build the release when you type `make`.
-
-In the `relx.config` file, we only need to tell `relx` that
-we want the release to include the `hello_erlang` application,
-and that we want an extended start script for convenience.
-`relx` will figure out which other applications are required
-by looking into the `.app` files for dependencies.
+You can then open the `src/hello_handler.erl` file and modify
+the `handle/2` function like this to send a reply.
 
 
 ``` erlang
 ``` erlang
-{release, {hello_erlang, "1"}, [hello_erlang]}.
-{extended_start_script, true}.
+handle(Req, State=#state{}) ->
+	{ok, Req2} = cowboy_req:reply(200,
+		[{<<"content-type">>, <<"text/plain">>}],
+		<<"Hello Erlang!">>,
+		Req),
+	{ok, Req2, State}.
 ```
 ```
 
 
-The `release` value is used to specify the release name, its
-version, and the applications to be included.
-
-We can now build and start the release.
-
-``` bash
-$ make
-$ ./_rel/hello_erlang/bin/hello_erlang console
-```
+What the above code does is send a `200 OK` reply, with the
+`content-type` header set to `text/plain` and the response
+body set to `Hello Erlang!`.
 
 
-If you then access `http://localhost:8080` using your browser,
-you should receive a nice greet!
+If you build the release, start it and open ^http://localhost:8080
+in your browser, you should get a nice `Hello Erlang!` displayed!