From 8d436c4744437e4b56d833e561613d0c9cd0fcab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Fri, 1 Aug 2014 14:27:04 +0200 Subject: Update the Getting started chapter to new erlang.mk Length of the chapter divided by 2! \o/ --- doc/src/guide/getting_started.ezdoc | 349 +++++++++++------------------------- 1 file changed, 106 insertions(+), 243 deletions(-) (limited to 'doc') diff --git a/doc/src/guide/getting_started.ezdoc b/doc/src/guide/getting_started.ezdoc index ff34699..81fbc99 100644 --- a/doc/src/guide/getting_started.ezdoc +++ b/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 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 $ mkdir 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. -:: 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 --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 -$ 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 -{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! -- cgit v1.2.3