From 078d686a0ac0aed212db97d73bd1e4a9387a4956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 6 Jul 2014 13:10:35 +0200 Subject: Provide installable man pages make docs: generate Markdown and man pages in doc/ make install-docs: install man pages to be usable directly Docs are generated from the ezdoc files in doc/src/. --- doc/src/guide/http_handlers.ezdoc | 145 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 doc/src/guide/http_handlers.ezdoc (limited to 'doc/src/guide/http_handlers.ezdoc') diff --git a/doc/src/guide/http_handlers.ezdoc b/doc/src/guide/http_handlers.ezdoc new file mode 100644 index 0000000..9a450a6 --- /dev/null +++ b/doc/src/guide/http_handlers.ezdoc @@ -0,0 +1,145 @@ +::: Handling plain HTTP requests + +The simplest way to handle a request is by writing a +plain HTTP handler. It is modeled after Erlang/OTP's +gen_server behaviour, although simplified, as Cowboy +will simply call the three callbacks sequentially. + +:: Initialization + +The first callback, `init/3`, is common to all handlers, +as it is used to identify the type of handler. Plain +HTTP handlers just return `ok`. + +``` erlang +init(_Type, Req, _Opts) -> + {ok, Req, no_state}. +``` + +This function receives the name of the transport and +protocol modules used for processing the request. +They can be used to quickly dismiss requests. For +example the following handler will crash when accessed +using TCP instead of SSL. + +``` erlang +init({ssl, _}, Req, _Opts) -> + {ok, Req, no_state}. +``` + +This function also receives the options associated with +this route that you configured previously. If your +handler does not use options, then it is recommended +you match the value `[]` directly to quickly detect +configuration errors. + +``` erlang +init(_Type, Req, []) -> + {ok, Req, no_state}. +``` + +You do not need to validate the options unless they +are user configured. If they are, and there's a +configuration error, you may choose to crash. For +example, this will crash if the required `lang` +option is not found. + +``` erlang +init(_Type, Req, Opts) -> + {_, _Lang} = lists:keyfind(lang, 1, Opts), + {ok, Req, no_state}. +``` + +If your users are unlikely to figure out the issue +without explanations, then you should send a more +meaningful error back to the user. Since we already +replied to the user, there's no need for us to +continue with the handler code, so we use the +`shutdown` return value to stop early. + +``` erlang +init(_Type, Req, Opts) -> + case lists:keyfind(lang, 1, Opts) of + false -> + {ok, Req2} = cowboy_req:reply(500, [ + {<<"content-type">>, <<"text/plain">>} + ], "Missing option 'lang'.", Req), + {shutdown, Req2, no_state}; + _ -> + {ok, Req, no_state} + end. +``` + +Once the options have been validated, we can use them +safely. So we need to pass them onward to the rest of +the handler. That's what the third element of the return +tuple, the state, is for. + +We recommend that you create a state record for this. +The record will make your handler code clearer and +will allow you to better use Dialyzer for type checking. + +``` erlang +-record(state, { + lang :: en | fr + %% More fields here. +}). + +init(_Type, Req, Opts) -> + {_, Lang} = lists:keyfind(lang, 1, Opts), + {ok, Req, #state{lang=Lang}}. +``` + +:: Handling the request + +The second callback, `handle/2`, is specific to plain HTTP +handlers. It's where you, wait for it, handle the request. + +A handle function that does nothing would look like this: + +``` erlang +handle(Req, State) -> + {ok, Req, State}. +``` + +There's no other return value. To obtain information about +the request, or send a response, you would use the Req object +here. The Req object is documented in its own chapter. + +The following handle function will send a fairly original response. + +``` erlang +handle(Req, State) -> + {ok, Req2} = cowboy_req:reply(200, [ + {<<"content-type">>, <<"text/plain">>} + ], <<"Hello World!">>, Req), + {ok, Req2, State}. +``` + +:: Cleaning up + +The third and last callback, `terminate/3`, will most likely +be empty in your handler. + +``` erlang +terminate(_Reason, Req, State) -> + ok. +``` + +This callback is strictly reserved for any required cleanup. +You cannot send a response from this function. There is no +other return value. + +If you used the process dictionary, timers, monitors or may +be receiving messages, then you can use this function to clean +them up, as Cowboy might reuse the process for the next +keep-alive request. + +The chances of any of this happening in your handler are pretty +thin however. The use of the process dictionary is discouraged +in Erlang code in general. And if you need to use timers, monitors +or to receive messages, you are better off with a loop handler, +a different kind of handler meant specifically for this use. + +This function is still available should you need it. It will +always be called. -- cgit v1.2.3