getting_started.ezdoc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. ::: Getting started
  2. Erlang is more than a language, it is also an operating system
  3. for your applications. Erlang developers rarely write standalone
  4. modules, they write libraries or applications, and then bundle
  5. those into what is called a release. A release contains the
  6. Erlang VM plus all applications required to run the node, so
  7. it can be pushed to production directly.
  8. This chapter walks you through all the steps of setting up
  9. Cowboy, writing your first application and generating your first
  10. release. At the end of this chapter you should know everything
  11. you need to push your first Cowboy application to production.
  12. :: Application skeleton
  13. Let's start by creating this application. We will simply call it
  14. `hello_erlang`. This application will have the following directory
  15. structure:
  16. ``` bash
  17. hello_erlang/
  18. src/
  19. hello_erlang.app.src
  20. hello_erlang_app.erl
  21. hello_erlang_sup.erl
  22. hello_handler.erl
  23. erlang.mk
  24. Makefile
  25. relx.config
  26. ```
  27. Once the release is generated, we will also have the following
  28. files added:
  29. ``` bash
  30. hello_erlang/
  31. ebin/
  32. hello_erlang.app
  33. hello_erlang_app.beam
  34. hello_erlang_sup.beam
  35. hello_handler.beam
  36. _rel/
  37. relx
  38. ```
  39. As you can probably guess, the `.app.src` file end up becoming
  40. the `.app` file, and the `.erl` files are compiled into `.beam`.
  41. Then, the whole release will be copied into the `_rel/` directory.
  42. The `.app` file contains various informations about the application.
  43. It contains its name, a description, a version, a list of modules,
  44. default configuration and more.
  45. Using a build system like ^"erlang.mk^https://github.com/extend/erlang.mk^,
  46. the list of modules will be included automatically in the `.app` file,
  47. so you don't need to manually put them in your `.app.src` file.
  48. For generating the release, we will use ^"relx^https://github.com/erlware/relx
  49. as it is a much simpler alternative to the tool coming with Erlang.
  50. First, create the `hello_erlang` directory. It should have the same name
  51. as the application within it. Then we create the `src` directory inside
  52. it, which will contain the source code for our application.
  53. ``` bash
  54. $ mkdir hello_erlang
  55. $ cd hello_erlang
  56. $ mkdir src
  57. ```
  58. Let's first create the `hello_erlang.app.src` file. It should be pretty
  59. straightforward for the most part. You can use the following template
  60. and change what you like in it.
  61. ``` erlang
  62. {application, hello_erlang, [
  63. {description, "Hello world with Cowboy!"},
  64. {vsn, "0.1.0"},
  65. {modules, []},
  66. {registered, [hello_erlang_sup]},
  67. {applications, [
  68. kernel,
  69. stdlib,
  70. cowboy
  71. ]},
  72. {mod, {hello_erlang_app, []}},
  73. {env, []}
  74. ]}.
  75. ```
  76. The `modules` line will be replaced with the list of modules during
  77. compilation. Make sure to leave this line even if you do not use it
  78. directly.
  79. The `registered` value indicates which processes are registered by this
  80. application. You will often only register the top-level supervisor
  81. of the application.
  82. The `applications` value lists the applications that must be started
  83. for this application to work. The Erlang release will start all the
  84. applications listed here automatically.
  85. The `mod` value defines how the application should be started. Erlang
  86. will use the `hello_erlang_app` module for starting the application.
  87. The `hello_erlang_app` module is what we call an application behavior.
  88. The application behavior must define two functions: `start/2` and
  89. `stop/1`, for starting and stopping the application. A typical
  90. application module would look like this:
  91. ``` erlang
  92. -module(hello_erlang_app).
  93. -behavior(application).
  94. -export([start/2]).
  95. -export([stop/1]).
  96. start(_Type, _Args) ->
  97. hello_erlang_sup:start_link().
  98. stop(_State) ->
  99. ok.
  100. ```
  101. That's not enough however. Since we are building a Cowboy based
  102. application, we also need to initialize Cowboy when we start our
  103. application.
  104. :: Setting up Cowboy
  105. Cowboy does nothing by default.
  106. Cowboy uses Ranch for handling the connections and provides convenience
  107. functions to start Ranch listeners.
  108. The `cowboy:start_http/4` function starts a listener for HTTP connections
  109. using the TCP transport. The `cowboy:start_https/4` function starts a
  110. listener for HTTPS connections using the SSL transport.
  111. Listeners are a group of processes that are used to accept and manage
  112. connections. The processes used specifically for accepting connections
  113. are called acceptors. The number of acceptor processes is unrelated to
  114. the maximum number of connections Cowboy can handle. Please refer to
  115. the ^"Ranch guide^http://ninenines.eu/docs/en/ranch/HEAD/guide/
  116. for in-depth information.
  117. Listeners are named. They spawn a given number of acceptors, listen for
  118. connections using the given transport options and pass along the protocol
  119. options to the connection processes. The protocol options must include
  120. the dispatch list for routing requests to handlers.
  121. The dispatch list is explained in greater details in the
  122. ^"Routing^routing^ chapter. For the purpose of this example
  123. we will simply map all URLs to our handler `hello_handler`,
  124. using the wildcard `_` for both the hostname and path parts
  125. of the URL.
  126. This is what the `hello_erlang_app:start/2` function looks like
  127. with Cowboy initialized.
  128. ``` erlang
  129. start(_Type, _Args) ->
  130. Dispatch = cowboy_router:compile([
  131. %% {URIHost, list({URIPath, Handler, Opts})}
  132. {'_', [{'_', hello_handler, []}]}
  133. ]),
  134. %% Name, NbAcceptors, TransOpts, ProtoOpts
  135. cowboy:start_http(my_http_listener, 100,
  136. [{port, 8080}],
  137. [{env, [{dispatch, Dispatch}]}]
  138. ),
  139. hello_erlang_sup:start_link().
  140. ```
  141. Do note that we told Cowboy to start listening on port 8080.
  142. You can change this value if needed.
  143. Our application doesn't need to start any process, as Cowboy
  144. will automatically start processes for every incoming
  145. connections. We are still required to have a top-level supervisor
  146. however, albeit a fairly small one.
  147. ``` erlang
  148. -module(hello_erlang_sup).
  149. -behavior(supervisor).
  150. -export([start_link/0]).
  151. -export([init/1]).
  152. start_link() ->
  153. supervisor:start_link({local, ?MODULE}, ?MODULE, []).
  154. init([]) ->
  155. {ok, {{one_for_one, 10, 10}, []}}.
  156. ```
  157. Finally, we need to write the code for handling incoming requests.
  158. :: Handling HTTP requests
  159. Cowboy features many kinds of handlers. For this simple example,
  160. we will just use the plain HTTP handler, which has three callback
  161. functions: `init/3`, `handle/2` and `terminate/3`. You can find more
  162. information about the arguments and possible return values of these
  163. callbacks in the
  164. ^"cowboy_http_handler function reference^http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_http_handler^.
  165. Our handler will only send a friendly hello back to the client.
  166. ``` erlang
  167. -module(hello_handler).
  168. -behavior(cowboy_http_handler).
  169. -export([init/3]).
  170. -export([handle/2]).
  171. -export([terminate/3]).
  172. init(_Type, Req, _Opts) ->
  173. {ok, Req, undefined_state}.
  174. handle(Req, State) ->
  175. {ok, Req2} = cowboy_req:reply(200, [
  176. {<<"content-type">>, <<"text/plain">>}
  177. ], <<"Hello World!">>, Req),
  178. {ok, Req2, State}.
  179. terminate(_Reason, _Req, _State) ->
  180. ok.
  181. ```
  182. The `Req` variable above is the Req object, which allows the developer
  183. to obtain information about the request and to perform a reply.
  184. Its usage is documented in the
  185. ^"cowboy_req function reference^http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_req^.
  186. The code for our application is ready, so let's build a release!
  187. :: Compiling
  188. First we need to download `erlang.mk`.
  189. ``` bash
  190. $ wget https://raw.github.com/extend/erlang.mk/master/erlang.mk
  191. $ ls
  192. src/
  193. erlang.mk
  194. ```
  195. Then we need to create a Makefile that will include `erlang.mk`
  196. for building our application. We need to define the Cowboy
  197. dependency in the Makefile. Thankfully `erlang.mk` already
  198. knows where to find Cowboy as it features a package index,
  199. so we can just tell it to look there.
  200. ``` Makefile
  201. PROJECT = hello_erlang
  202. DEPS = cowboy
  203. dep_cowboy = pkg://cowboy master
  204. include erlang.mk
  205. ```
  206. Note that when creating production nodes you will most likely
  207. want to use a specific version of Cowboy instead of `master`,
  208. and properly test your release every time you update Cowboy.
  209. If you type `make` in a shell now, your application should build
  210. as expected. If you get compilation errors, double check that you
  211. haven't made any typo when creating the previous files.
  212. ``` bash
  213. $ make
  214. ```
  215. :: Generating the release
  216. That's not all however, as we want to create a working release.
  217. For that purpose, we need to create a `relx.config` file. When
  218. this file exists, `erlang.mk` will automatically download `relx`
  219. and build the release when you type `make`.
  220. In the `relx.config` file, we only need to tell `relx` that
  221. we want the release to include the `hello_erlang` application,
  222. and that we want an extended start script for convenience.
  223. `relx` will figure out which other applications are required
  224. by looking into the `.app` files for dependencies.
  225. ``` erlang
  226. {release, {hello_erlang, "1"}, [hello_erlang]}.
  227. {extended_start_script, true}.
  228. ```
  229. The `release` value is used to specify the release name, its
  230. version, and the applications to be included.
  231. We can now build and start the release.
  232. ``` bash
  233. $ make
  234. $ ./_rel/hello_erlang/bin/hello_erlang console
  235. ```
  236. If you then access `http://localhost:8080` using your browser,
  237. you should receive a nice greet!