diff --git a/.gitignore b/.gitignore index d708ffc9..b1fa0b5a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ .erlang.mk.packages.* _rel deps +doc/man3 +doc/man7 +doc/markdown ebin logs relx diff --git a/Makefile b/Makefile index 168d8af1..70eec4f2 100644 --- a/Makefile +++ b/Makefile @@ -24,3 +24,55 @@ dep_gun = pkg://gun master # Standard targets. include erlang.mk + +# Documentation. + +dep_ezdoc = https://github.com/ninenines/ezdoc master +$(eval $(call dep_target,ezdoc)) + +build-doc-deps: $(DEPS_DIR)/ezdoc + $(MAKE) -C $(DEPS_DIR)/ezdoc + +define ezdoc_script +io:format("Building manual~n"), +[begin + AST = ezdoc:parse_file(F), + BF = filename:rootname(filename:basename(F)), + io:format(" ~s~n", [BF]), + file:write_file("doc/markdown/manual/" ++ BF ++ ".md", ezdoc_markdown:export(AST)), + case BF of + "cowboy" ++ _ when BF =/= "cowboy_app" -> + file:write_file("doc/man3/" ++ BF ++ ".3", ezdoc_man:export(3, AST)); + _ when BF =/= "index" -> + file:write_file("doc/man7/" ++ BF ++ ".7", ezdoc_man:export(7, AST)); + _ -> + ok + end +end || F <- filelib:wildcard("doc/src/manual/*.ezdoc")], +io:format("Building guide~n"), +[begin + AST = ezdoc:parse_file(F), + BF = filename:rootname(filename:basename(F)), + io:format(" ~s~n", [BF]), + file:write_file("doc/markdown/guide/" ++ BF ++ ".md", ezdoc_markdown:export(AST)) +end || F <- filelib:wildcard("doc/src/guide/*.ezdoc")], +io:format("Done.~n"), +init:stop(). +endef +export ezdoc_script + +docs: clean-docs build-doc-deps + @mkdir -p doc/man3 doc/man7 doc/markdown/guide doc/markdown/manual + $(gen_verbose) erl -noinput -pa ebin deps/ezdoc/ebin -eval "$$ezdoc_script" + @gzip doc/man3/*.3 doc/man7/*.7 + @cp doc/src/guide/*.png doc/markdown/guide + +clean-docs: + $(gen_verbose) rm -rf doc/man3 doc/man7 doc/markdown + +MAN_INSTALL_PATH ?= /usr/local/share/man + +install-docs: + mkdir -p $(MAN_INSTALL_PATH)/man3/ $(MAN_INSTALL_PATH)/man7/ + install -g 0 -o 0 -m 0644 doc/man3/*.gz $(MAN_INSTALL_PATH)/man3/ + install -g 0 -o 0 -m 0644 doc/man7/*.gz $(MAN_INSTALL_PATH)/man7/ diff --git a/README.md b/README.md index 8313bc6a..2919e63d 100644 --- a/README.md +++ b/README.md @@ -27,15 +27,23 @@ The SPDY implementation was sponsored by The project is currently sponsored by [Kato.im](https://kato.im). -Getting Started ---------------- +Online documentation +-------------------- - * [Read the guide](http://ninenines.eu/docs/en/cowboy/HEAD/guide) - * [Check the manual](http://ninenines.eu/docs/en/cowboy/HEAD/manual) - * Look at the examples in the `examples/` directory + * [User guide](http://ninenines.eu/docs/en/cowboy/HEAD/guide) + * [Function reference](http://ninenines.eu/docs/en/cowboy/HEAD/manual) -Support -------- +Offline documentation +--------------------- + + * While still online, run `make docs` + * Function reference man pages available in `doc/man3/` and `doc/man7/` + * Run `make install-docs` to install man pages on your system + * Full documentation in Markdown available in `doc/markdown/` + * Examples available in `examples/` + +Getting help +------------ * Official IRC Channel: #ninenines on irc.freenode.net * [Mailing Lists](http://lists.ninenines.eu) diff --git a/guide/architecture.md b/doc/src/guide/architecture.ezdoc similarity index 91% rename from guide/architecture.md rename to doc/src/guide/architecture.ezdoc index b799a37b..745505ab 100644 --- a/guide/architecture.md +++ b/doc/src/guide/architecture.ezdoc @@ -1,13 +1,11 @@ -Architecture -============ +::: Architecture Cowboy is a lightweight HTTP server. It is built on top of Ranch. Please see the Ranch guide for more information. -One process per connection --------------------------- +:: One process per connection It uses only one process per connection. The process where your code runs is the process controlling the socket. Using one process @@ -22,8 +20,7 @@ up before terminating the handling of the current request. This may include cleaning up the process dictionary, timers, monitoring and more. -Binaries --------- +:: Binaries It uses binaries. Binaries are more efficient than lists for representing strings because they take less memory space. Processing @@ -31,16 +28,14 @@ performance can vary depending on the operation. Binaries are known for generally getting a great boost if the code is compiled natively. Please see the HiPE documentation for more details. -Date header ------------ +:: Date header Because querying for the current date and time can be expensive, Cowboy generates one `Date` header value every second, shares it to all other processes, which then simply copy it in the response. This allows compliance with HTTP/1.1 with no actual performance loss. -Max connections ---------------- +:: Max connections By default the maximum number of active connections is set to a generally accepted big enough number. This is meant to prevent having diff --git a/guide/broken_clients.md b/doc/src/guide/broken_clients.ezdoc similarity index 91% rename from guide/broken_clients.md rename to doc/src/guide/broken_clients.ezdoc index ac9924c3..26568a37 100644 --- a/guide/broken_clients.md +++ b/doc/src/guide/broken_clients.ezdoc @@ -1,5 +1,4 @@ -Dealing with broken clients -=========================== +::: Dealing with broken clients There exists a very large number of implementations for the HTTP protocol. Most widely used clients, like browsers, @@ -16,8 +15,7 @@ That means clients that ignore the HTTP standard completely may fail to understand Cowboy's responses. There are of course workarounds. This chapter aims to cover them. -Lowercase headers ------------------ +:: Lowercase headers Cowboy converts all headers it receives to lowercase, and similarly sends back headers all in lowercase. Some broken @@ -39,8 +37,7 @@ because the specification explicitly says all headers are lowercase, unlike HTTP which allows any case but treats them as case insensitive. -Camel-case headers ------------------- +:: Camel-case headers Sometimes it is desirable to keep the actual case used by clients, for example when acting as a proxy between two broken @@ -48,8 +45,7 @@ implementations. There is no easy solution for this other than forking the project and editing the `cowboy_protocol` file directly. -Chunked transfer-encoding -------------------------- +:: Chunked transfer-encoding Sometimes an HTTP client advertises itself as HTTP/1.1 but does not support chunked transfer-encoding. This is invalid diff --git a/guide/cookies.md b/doc/src/guide/cookies.ezdoc similarity index 97% rename from guide/cookies.md rename to doc/src/guide/cookies.ezdoc index bfc86512..fe9246cc 100644 --- a/guide/cookies.md +++ b/doc/src/guide/cookies.ezdoc @@ -1,5 +1,4 @@ -Using cookies -============= +::: Using cookies Cookies are a mechanism allowing applications to maintain state on top of the stateless HTTP protocol. @@ -49,8 +48,7 @@ that run from HTTPS webpages. Finally, cookies can be restricted to HTTP and HTTPS requests, essentially disabling their access from client-side scripts. -Setting cookies ---------------- +:: Setting cookies By default, cookies you set are defined for the session. @@ -112,8 +110,7 @@ Req2 = cowboy_req:set_resp_cookie(<<"sessionid">>, SessionID, [ Cookies may also be set client-side, for example using Javascript. -Reading cookies ---------------- +:: Reading cookies As we said, the client sends cookies with every request. But unlike the server, the client only sends the cookie diff --git a/guide/erlang_beginners.md b/doc/src/guide/erlang_beginners.ezdoc similarity index 80% rename from guide/erlang_beginners.md rename to doc/src/guide/erlang_beginners.ezdoc index 7778dee0..f62543f6 100644 --- a/guide/erlang_beginners.md +++ b/doc/src/guide/erlang_beginners.ezdoc @@ -1,5 +1,4 @@ -Erlang for beginners -==================== +::: Erlang for beginners Chances are you are interested in using Cowboy, but have no idea how to write an Erlang program. Fear not! This @@ -9,11 +8,10 @@ We recommend two books for beginners. You should read them both at some point, as they cover Erlang from two entirely different perspectives. -Learn You Some Erlang for Great Good! -------------------------------------- +:: Learn You Some Erlang for Great Good! The quickest way to get started with Erlang is by reading -a book with the funny name of [LYSE](http://learnyousomeerlang.com), +a book with the funny name of ^"LYSE^http://learnyousomeerlang.com^, as we affectionately call it. It will get right into the syntax and quickly answer the questions @@ -24,13 +22,12 @@ You can read an early version of the book online for free, but you really should buy the much more refined paper and ebook versions. -Programming Erlang ------------------- +:: Programming Erlang After writing some code, you will probably want to understand the very concepts that make Erlang what it is today. These are best explained by Joe Armstrong, the godfather of Erlang, -in his book [Programming Erlang](http://pragprog.com/book/jaerlang2/programming-erlang). +in his book ^"Programming Erlang^http://pragprog.com/book/jaerlang2/programming-erlang^. Instead of going into every single details of the language, Joe focuses on the central concepts behind Erlang, and shows diff --git a/guide/erlang_web.md b/doc/src/guide/erlang_web.ezdoc similarity index 96% rename from guide/erlang_web.md rename to doc/src/guide/erlang_web.ezdoc index fa3d9221..42fcd344 100644 --- a/guide/erlang_web.md +++ b/doc/src/guide/erlang_web.ezdoc @@ -1,8 +1,6 @@ -Erlang and the Web -================== +::: Erlang and the Web -The Web is concurrent ---------------------- +:: The Web is concurrent When you access a website there is little concurrency involved. A few connections are opened and requests @@ -55,8 +53,7 @@ will also connect to various applications on the Internet. Only Erlang is prepared to deal with what's coming. -The Web is soft real time -------------------------- +:: The Web is soft real time What does soft real time mean, you ask? It means we want the operations done as quickly as possible, and in the case of @@ -85,8 +82,7 @@ can guarantee stable low latency of operations. Erlang provides the guarantees that the soft real time Web requires. -The Web is asynchronous ------------------------ +:: The Web is asynchronous Long ago, the Web was synchronous because HTTP was synchronous. You fired a request, and then waited for a response. Not anymore. @@ -118,8 +114,7 @@ Erlang is by nature asynchronous and really good at it thanks to the great engineering that has been done in the VM over the years. It's only natural that it's so good at dealing with the asynchronous Web. -The Web is omnipresent ----------------------- +:: The Web is omnipresent The Web has taken a very important part of our lives. We're connected at all times, when we're on our phone, using our computer, @@ -172,8 +167,7 @@ down, or even a data center entirely. Fault tolerance and distribution are important today, and will be vital in the future of the Web. Erlang is ready. -Erlang is the ideal platform for the Web ----------------------------------------- +:: Erlang is the ideal platform for the Web Erlang provides all the important features that the Web requires or will require in the near future. Erlang is a perfect match diff --git a/guide/getting_started.md b/doc/src/guide/getting_started.ezdoc similarity index 92% rename from guide/getting_started.md rename to doc/src/guide/getting_started.ezdoc index a5f811db..ff34699e 100644 --- a/guide/getting_started.md +++ b/doc/src/guide/getting_started.ezdoc @@ -1,5 +1,4 @@ -Getting started -=============== +::: Getting started Erlang is more than a language, it is also an operating system for your applications. Erlang developers rarely write standalone @@ -13,14 +12,13 @@ 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 --------------------- +:: Application skeleton Let's start by creating this application. We will simply call it `hello_erlang`. This application will have the following directory structure: -``` +``` bash hello_erlang/ src/ hello_erlang.app.src @@ -35,7 +33,7 @@ hello_erlang/ Once the release is generated, we will also have the following files added: -``` +``` bash hello_erlang/ ebin/ hello_erlang.app @@ -54,11 +52,11 @@ 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), +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) +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 @@ -129,8 +127,7 @@ That's not enough however. Since we are building a Cowboy based application, we also need to initialize Cowboy when we start our application. -Setting up Cowboy ------------------ +:: Setting up Cowboy Cowboy does nothing by default. @@ -145,7 +142,7 @@ 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/) +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 @@ -154,7 +151,7 @@ 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.md) chapter. For the purpose of this example +^"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. @@ -200,15 +197,14 @@ init([]) -> Finally, we need to write the code for handling incoming requests. -Handling HTTP 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). +^"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. @@ -236,12 +232,11 @@ terminate(_Reason, _Req, _State) -> 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). +^"cowboy_req function reference^http://ninenines.eu/docs/en/cowboy/HEAD/manual/cowboy_req^. The code for our application is ready, so let's build a release! -Compiling ---------- +:: Compiling First we need to download `erlang.mk`. @@ -279,8 +274,7 @@ haven't made any typo when creating the previous files. $ make ``` -Generating the release ----------------------- +:: 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 diff --git a/guide/hooks.md b/doc/src/guide/hooks.ezdoc similarity index 97% rename from guide/hooks.md rename to doc/src/guide/hooks.ezdoc index b2e0c50a..edef9717 100644 --- a/guide/hooks.md +++ b/doc/src/guide/hooks.ezdoc @@ -1,12 +1,10 @@ -Hooks -===== +::: Hooks Cowboy provides two hooks. `onrequest` is called once the request line and headers have been received. `onresponse` is called just before sending the response. -Onrequest ---------- +:: Onrequest The `onrequest` hook is called as soon as Cowboy finishes fetching the request headers. It occurs before any other processing, including @@ -43,8 +41,7 @@ debug_hook(Req) -> Make sure to always return the last request object obtained. -Onresponse ----------- +:: Onresponse The `onresponse` hook is called right before sending the response to the socket. It can be used for the purposes of logging responses, diff --git a/guide/http_handlers.md b/doc/src/guide/http_handlers.ezdoc similarity index 96% rename from guide/http_handlers.md rename to doc/src/guide/http_handlers.ezdoc index b1e2d5cf..9a450a68 100644 --- a/guide/http_handlers.md +++ b/doc/src/guide/http_handlers.ezdoc @@ -1,13 +1,11 @@ -Handling plain HTTP requests -============================ +::: 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 --------------- +:: Initialization The first callback, `init/3`, is common to all handlers, as it is used to identify the type of handler. Plain @@ -92,8 +90,7 @@ init(_Type, Req, Opts) -> {ok, Req, #state{lang=Lang}}. ``` -Handling the request --------------------- +:: Handling the request The second callback, `handle/2`, is specific to plain HTTP handlers. It's where you, wait for it, handle the request. @@ -119,8 +116,7 @@ handle(Req, State) -> {ok, Req2, State}. ``` -Cleaning up ------------ +:: Cleaning up The third and last callback, `terminate/3`, will most likely be empty in your handler. diff --git a/guide/http_req_life.md b/doc/src/guide/http_req_life.ezdoc similarity index 94% rename from guide/http_req_life.md rename to doc/src/guide/http_req_life.ezdoc index 1462b590..5fd8486b 100644 --- a/guide/http_req_life.md +++ b/doc/src/guide/http_req_life.ezdoc @@ -1,12 +1,10 @@ -The life of a request -===================== +::: The life of a request This chapter explains the different steps a request goes through until a response is sent, along with details of the Cowboy implementation. -Request/response ----------------- +:: Request/response As you already know, HTTP clients connect to the server and send a request for a resource; the server then sends a @@ -20,7 +18,7 @@ add like writing logs. Requests take the following route in Cowboy: - +^"HTTP request/response flowchart^!http_req_resp.png This shows the default middlewares, but they may be configured differently in your setup. The dark green @@ -44,8 +42,7 @@ When a response is sent, you can optionally modify it or act upon it by enabling the `onresponse` hook. By default the response is sent directly to the client. -And then? ---------- +:: And then? Behavior depends on what protocol is in use. @@ -62,8 +59,7 @@ asynchronously on the same connection. Details on what this means for your application is described in this chapter. -Keep-alive (HTTP/1.1) ---------------------- +:: Keep-alive (HTTP/1.1) With HTTP/1.1, the connection may be left open for subsequent requests to come. This mechanism is called @@ -110,8 +106,7 @@ But it also means you need to clean up if you do have code with side effects. The `terminate/3` function can be used for this purpose. -Pipelining (HTTP/1.1) ---------------------- +:: Pipelining (HTTP/1.1) While HTTP is designed as a sequential protocol, with the client sending a request and then waiting for the @@ -128,8 +123,7 @@ static files for example. This is handled automatically by the server. -Asynchronous requests (SPDY) ----------------------------- +:: Asynchronous requests (SPDY) In SPDY, the client can send a request at any time. And the server can send a response at any time too. diff --git a/guide/http_req_resp.png b/doc/src/guide/http_req_resp.png similarity index 100% rename from guide/http_req_resp.png rename to doc/src/guide/http_req_resp.png diff --git a/guide/http_req_resp.svg b/doc/src/guide/http_req_resp.svg similarity index 100% rename from guide/http_req_resp.svg rename to doc/src/guide/http_req_resp.svg diff --git a/doc/src/guide/index.ezdoc b/doc/src/guide/index.ezdoc new file mode 100644 index 00000000..38b2ac0c --- /dev/null +++ b/doc/src/guide/index.ezdoc @@ -0,0 +1,58 @@ +::: Cowboy User Guide + +The Cowboy User Guide explores the modern Web and how to make +best use of Cowboy for writing powerful web applications. + +:: Introducing Cowboy + +* ^"Introduction^introduction +* ^"The modern Web^modern_web +* ^"Erlang and the Web^erlang_web +* ^"Erlang for beginners^erlang_beginners +* ^"Getting started^getting_started + +:: HTTP + +* ^"The life of a request^http_req_life +* ^"Routing^routing +* ^"Handling plain HTTP requests^http_handlers +* ^"The Req object^req +* ^"Reading the request body^req_body +* ^"Sending a response^resp +* ^"Using cookies^cookies + +:: Multipart + +* ^"Introduction to multipart^multipart_intro +* ^"Multipart requests^multipart_req + +:: Static files + +* ^"Static handler^static_handlers + +:: REST + +* ^"REST principles^rest_principles +* ^"Handling REST requests^rest_handlers +* ^"REST flowcharts^rest_flowcharts +* ^"Designing a resource handler^resource_design + +:: Websocket + +* ^"The Websocket protocol^ws_protocol +* ^"Handling Websocket connections^ws_handlers + +:: Server push + +* ^"Loop handlers^loop_handlers + +:: Pluggable interface + +* ^"Middlewares^middlewares +* ^"Protocol upgrades^upgrade_protocol +* ^"Hooks^hooks + +:: Internals + +* ^"Architecture^architecture +* ^"Dealing with broken clients^broken_clients diff --git a/guide/introduction.md b/doc/src/guide/introduction.ezdoc similarity index 93% rename from guide/introduction.md rename to doc/src/guide/introduction.ezdoc index 0af90397..7f77fccc 100644 --- a/guide/introduction.md +++ b/doc/src/guide/introduction.ezdoc @@ -1,5 +1,4 @@ -Introduction -============ +::: Introduction Cowboy is a small, fast and modular HTTP server written in Erlang. @@ -15,8 +14,7 @@ Cowboy is clean Erlang code. It includes hundreds of tests and its code is fully compliant with the Dialyzer. It is also well documented and features both a Function Reference and a User Guide. -Prerequisites -------------- +:: Prerequisites No Erlang knowledge is required for reading this guide. The reader will be introduced to Erlang concepts and redirected to reference material @@ -25,8 +23,7 @@ whenever necessary. Knowledge of the HTTP protocol is recommended but not required, as it will be detailed throughout the guide. -Supported platforms -------------------- +:: Supported platforms Cowboy is tested and supported on Linux. @@ -40,8 +37,7 @@ Cowboy is developed for Erlang R15B+. Cowboy may be compiled on earlier Erlang versions with small source code modifications but there is no guarantee that it will work as expected. -Conventions ------------ +:: Conventions In the HTTP protocol, the method name is case sensitive. All standard method names are uppercase. diff --git a/guide/loop_handlers.md b/doc/src/guide/loop_handlers.ezdoc similarity index 95% rename from guide/loop_handlers.md rename to doc/src/guide/loop_handlers.ezdoc index 86894530..fba4feb7 100644 --- a/guide/loop_handlers.md +++ b/doc/src/guide/loop_handlers.ezdoc @@ -1,5 +1,4 @@ -Loop handlers -============= +::: Loop handlers Loop handlers are a special kind of HTTP handlers used when the response can not be sent right away. The handler enters instead @@ -25,8 +24,7 @@ and feed these messages to the `info/3` callback. It also features the `init/3` and `terminate/3` callbacks which work the same as for plain HTTP handlers. -Initialization --------------- +:: Initialization The `init/3` function must return a `loop` tuple to enable loop handler behavior. This tuple may optionally contain @@ -49,8 +47,7 @@ init(_Type, Req, _Opts) -> {loop, Req, undefined_state, 30000, hibernate}. ``` -Receive loop ------------- +:: Receive loop Once initialized, Cowboy will wait for messages to arrive in the process' mailbox. When a message arrives, Cowboy @@ -84,8 +81,7 @@ This will instruct Cowboy to end the request. Otherwise a `loop` tuple should be returned. -Streaming loop --------------- +:: Streaming loop Another common case well suited for loop handlers is streaming data received in the form of Erlang messages. @@ -111,18 +107,16 @@ info(_Msg, Req, State) -> {loop, Req, State}. ``` -Cleaning up ------------ +:: Cleaning up It is recommended that you set the connection header to `close` when replying, as this process may be reused for a subsequent request. -Please refer to the [HTTP handlers chapter](http_handlers.md) +Please refer to the ^"HTTP handlers chapter^http_handlers for general instructions about cleaning up. -Timeout -------- +:: Timeout By default Cowboy will not attempt to close the connection if there is no activity from the client. This is not always @@ -138,8 +132,7 @@ so there is a configurable limit for it. The default buffer size is of 5000 bytes, but it may be changed by setting the `loop_max_buffer` middleware environment value. -Hibernate ---------- +:: Hibernate To save memory, you may hibernate the process in between messages received. This is done by returning the atom diff --git a/guide/middlewares.md b/doc/src/guide/middlewares.ezdoc similarity index 81% rename from guide/middlewares.md rename to doc/src/guide/middlewares.ezdoc index 341a0e22..e33abfb0 100644 --- a/guide/middlewares.md +++ b/doc/src/guide/middlewares.ezdoc @@ -1,5 +1,4 @@ -Middlewares -=========== +::: Middlewares Cowboy delegates the request processing to middleware components. By default, two middlewares are defined, for the routing and handling @@ -12,8 +11,7 @@ change the chain of middlewares as needed. Cowboy will execute all middlewares in the given order, unless one of them decides to stop processing. -Usage ------ +:: Usage Middlewares only need to implement a single callback: `execute/2`. It is defined in the `cowboy_middleware` behavior. @@ -22,10 +20,11 @@ This callback has two arguments. The first is the `Req` object. The second is the environment. Middlewares can return one of four different values: - * `{ok, Req, Env}` to continue the request processing - * `{suspend, Module, Function, Args}` to hibernate - * `{halt, Req}` to stop processing and move on to the next request - * `{error, StatusCode, Req}` to reply an error and close the socket + +* `{ok, Req, Env}` to continue the request processing +* `{suspend, Module, Function, Args}` to hibernate +* `{halt, Req}` to stop processing and move on to the next request +* `{error, StatusCode, Req}` to reply an error and close the socket Of note is that when hibernating, processing will resume on the given MFA, discarding all previous stacktrace. Make sure you keep the `Req` @@ -36,8 +35,7 @@ to send an error back to the socket, the process will just crash. It is up to the middleware to make sure that a reply is sent if something goes wrong. -Configuration -------------- +:: Configuration The middleware environment is defined as the `env` protocol option. In the previous chapters we saw it briefly when we needed to pass @@ -45,8 +43,9 @@ the routing information. It is a list of tuples with the first element being an atom and the second any Erlang term. Two values in the environment are reserved: - * `listener` contains the name of the listener - * `result` contains the result of the processing + +* `listener` contains the name of the listener +* `result` contains the result of the processing The `listener` value is always defined. The `result` value can be set by any middleware. If set to anything other than `ok`, Cowboy @@ -58,15 +57,13 @@ environment values to perform. You can update the environment by calling the `cowboy:set_env/3` convenience function, adding or replacing a value in the environment. -Routing middleware ------------------- +:: Routing middleware The routing middleware requires the `dispatch` value. If routing succeeds, it will put the handler name and options in the `handler` and `handler_opts` values of the environment, respectively. -Handler middleware ------------------- +:: Handler middleware The handler middleware requires the `handler` and `handler_opts` values. It puts the result of the request handling into `result`. diff --git a/guide/modern_web.md b/doc/src/guide/modern_web.ezdoc similarity index 97% rename from guide/modern_web.md rename to doc/src/guide/modern_web.ezdoc index 53670a4d..1c2c3427 100644 --- a/guide/modern_web.md +++ b/doc/src/guide/modern_web.ezdoc @@ -1,5 +1,4 @@ -The modern Web -============== +::: The modern Web Let's take a look at various technologies from the beginnings of the Web up to this day, and get a preview of what's @@ -9,8 +8,7 @@ Cowboy is compatible with all the technology cited in this chapter except of course HTTP/2.0 which has no implementation in the wild at the time of writing. -The prehistoric Web -------------------- +:: The prehistoric Web HTTP was initially created to serve HTML pages and only had the GET method for retrieving them. This initial @@ -31,8 +29,7 @@ this. Most improvements done in recent years focused on reducing this load time and reducing the latency of the requests. -HTTP/1.1 --------- +:: HTTP/1.1 HTTP/1.1 quickly followed and added a keep-alive mechanism to allow using the same connection for many requests, as @@ -50,8 +47,7 @@ clients to perform what is called as pipelining: sending many requests in a row, and then processing the responses which will be received in the same order as the requests. -REST ----- +:: REST The design of HTTP/1.1 was influenced by the REST architectural style. REST, or REpresentational State Transfer, is a style of @@ -76,8 +72,7 @@ to implement RESTful systems. REST is most often used when designing web application APIs which are generally meant to be used by executable code directly. -XmlHttpRequest --------------- +:: XmlHttpRequest Also know as AJAX, this technology allows Javascript code running on a web page to perform asynchronous requests to the server. @@ -93,8 +88,7 @@ This is of course still requests initiated by the client, the server still had no way of pushing data to the client on its own, so new technology appeared to allow that. -Long-polling ------------- +:: Long-polling Polling was a technique used to overcome the fact that the server cannot push data directly to the client. Therefore the client had @@ -122,8 +116,7 @@ You probably guessed by now that long-polling is a hack, and like most hacks it can suffer from unforeseen issues, in this case it doesn't always play well with proxies. -HTML5 ------ +:: HTML5 HTML5 is, of course, the HTML version after HTML4. But HTML5 emerged to solve a specific problem: dynamic web applications. @@ -147,8 +140,7 @@ events from the server. The solution went on to become HTML5. At the time of writing it is being standardized. -EventSource ------------ +:: EventSource EventSource, sometimes also called Server-Sent Events, is a technology allowing servers to push data to HTML5 applications. @@ -167,8 +159,7 @@ UTF-8 encoded text data. Binary data and text data encoded differently are not allowed by the protocol. A heavier but more generic approach can be found in Websocket. -Websocket ---------- +:: Websocket Websocket is a protocol built on top of HTTP/1.1 that provides a two-ways communication channel between the client and the @@ -188,8 +179,7 @@ A Websocket connection can be used to transfer any kind of data, small or big, text or binary. Because of this Websocket is sometimes used for communication between systems. -SPDY ----- +:: SPDY SPDY is an attempt to reduce page loading time by opening a single connection per server, keeping it open for subsequent @@ -213,8 +203,7 @@ to a SPDY connection seamlessly if the protocol supports it. The protocol itself has a few shortcomings which are being fixed in HTTP/2.0. -HTTP/2.0 --------- +:: HTTP/2.0 HTTP/2.0 is the long-awaited update to the HTTP/1.1 protocol. It is based on SPDY although a lot has been improved at the diff --git a/guide/multipart_intro.md b/doc/src/guide/multipart_intro.ezdoc similarity index 94% rename from guide/multipart_intro.md rename to doc/src/guide/multipart_intro.ezdoc index dde4099b..b9a7fa93 100644 --- a/guide/multipart_intro.md +++ b/doc/src/guide/multipart_intro.ezdoc @@ -1,5 +1,4 @@ -Introduction to multipart -========================= +::: Introduction to multipart Multipart originates from MIME, an Internet standard that extends the format of emails. Multipart messages are a @@ -19,8 +18,7 @@ Multipart is of course not required for uploading files, it is only required when you want to do so through HTML forms. -Structure ---------- +:: Structure A multipart message is a list of parts. Parts may contain either a multipart message or a non-multipart @@ -28,8 +26,7 @@ content-type. This allows parts to be arranged in a tree structure, although this is a rare case as far as the Web is concerned. -Form-data ---------- +:: Form-data In the normal case, when a form is submitted, the browser will use the `application/x-www-form-urlencoded` diff --git a/guide/multipart_req.md b/doc/src/guide/multipart_req.ezdoc similarity index 94% rename from guide/multipart_req.md rename to doc/src/guide/multipart_req.ezdoc index a56c70e3..a807e48b 100644 --- a/guide/multipart_req.md +++ b/doc/src/guide/multipart_req.ezdoc @@ -1,5 +1,4 @@ -Multipart requests -================== +::: Multipart requests You can read and parse multipart messages using the Req object directly. @@ -7,8 +6,7 @@ Req object directly. Cowboy defines two functions that allows you to get information about each part and read their contents. -Checking the content-type -------------------------- +:: Checking the content-type While there is a variety of multipart messages, the most common on the Web is `multipart/form-data`. It's @@ -23,8 +21,7 @@ has been sent by parsing the `content-type` header. = cowboy_req:parse_header(<<"content-type">>, Req). ``` -Reading a multipart message ---------------------------- +:: Reading a multipart message To read a message you have to iterate over all its parts. Then, for each part, you can inspect its headers @@ -84,8 +81,7 @@ to 8MB. This can of course be overriden. Both functions can take a second argument, the same list of options that will be passed to `cowboy_req:body/2` function. -Skipping unwanted parts ------------------------ +:: Skipping unwanted parts If you do not want to read a part's body, you can skip it. Skipping is easy. If you do not call the function to read diff --git a/guide/req.md b/doc/src/guide/req.ezdoc similarity index 96% rename from guide/req.md rename to doc/src/guide/req.ezdoc index 074f3256..95011583 100644 --- a/guide/req.md +++ b/doc/src/guide/req.ezdoc @@ -1,12 +1,10 @@ -The Req object -============== +::: The Req object The Req object is this variable that you will use to obtain information about a request, read the body of the request and send a response. -A special variable ------------------- +:: A special variable While we call it an "object", it is not an object in the OOP sense of the term. In fact it is completely opaque @@ -33,8 +31,7 @@ It also caches the result of operations performed on the immutable state. That means that some calls will give a result much faster when called many times. -Overview of the cowboy_req interface ------------------------------------- +:: Overview of the cowboy_req interface The `cowboy_req` interface is divided in four groups of functions, each having a well defined return type @@ -72,8 +69,7 @@ This chapter covers most of the first group, plus a few other functions. The next few chapters cover cookies handling, reading the request body and sending a response. -Request -------- +:: Request When a client performs a request, it first sends a few required values. They are sent differently depending on the protocol @@ -109,8 +105,7 @@ Do note however that clients claiming to implement one version of the protocol does not mean they implement it fully, or even properly. -Bindings --------- +:: Bindings After routing the request, bindings are available. Bindings are these parts of the host or path that you chose to extract @@ -153,8 +148,7 @@ or get `undefined` otherwise. {PathInfo, Req2} = cowboy_req:path_info(Req). ``` -Query string ------------- +:: Query string The query string can be obtained directly. @@ -181,8 +175,7 @@ Finally, you can obtain all query string values. {AllValues, Req2} = cowboy_req:qs_vals(Req). ``` -Request URL ------------ +:: Request URL You can reconstruct the full URL of the resource. @@ -197,8 +190,7 @@ path and query string. {BaseURL, Req2} = cowboy_req:host_url(Req). ``` -Headers -------- +:: Headers Cowboy allows you to obtain the header values as string, or parsed into a more meaningful representation. @@ -258,8 +250,7 @@ manual. Also note that the result of parsing is cached, so calling this function multiple times for the same values will not have a significant performance impact. -Meta ----- +:: Meta Cowboy will sometimes associate some meta information with the request. Built-in meta values are listed in the manual @@ -285,8 +276,7 @@ an `atom()`. Req2 = cowboy_req:set_meta(the_answer, 42, Req). ``` -Peer ----- +:: Peer You can obtain the peer address and port number. This is not necessarily the actual IP and port of the client, but @@ -296,8 +286,7 @@ rather the one of the machine that connected to the server. {{IP, Port}, Req2} = cowboy_req:peer(Req). ``` -Reducing the memory footprint ------------------------------ +:: Reducing the memory footprint When you are done reading information from the request object and know you are not going to access it anymore, for example diff --git a/guide/req_body.md b/doc/src/guide/req_body.ezdoc similarity index 91% rename from guide/req_body.md rename to doc/src/guide/req_body.ezdoc index 5e07fbe4..44f32f80 100644 --- a/guide/req_body.md +++ b/doc/src/guide/req_body.ezdoc @@ -1,5 +1,4 @@ -Reading the request body -======================== +::: Reading the request body The Req object also allows you to read the request body. @@ -17,8 +16,7 @@ parse in a single call for form urlencoded formats or multipart. All of these except multipart are covered in this chapter. Multipart is covered later on in the guide. -Check for request body ----------------------- +:: Check for request body You can check whether a body was sent with the request. @@ -33,8 +31,7 @@ Note that it is generally safe to assume that a body is sent for `POST`, `PUT` and `PATCH` requests, without having to explicitly check for it. -Request body length -------------------- +:: Request body length You can obtain the body length if it was sent with the request. @@ -49,8 +46,7 @@ there's a body but no length is given, this means that the chunked transfer-encoding was used. You can read chunked bodies by using the stream functions. -Reading the body ----------------- +:: Reading the body You can read the whole body directly in one call. @@ -78,8 +74,7 @@ If the body is larger than the limit, then Cowboy will return a `more` tuple instead, allowing you to stream it if you would like to. -Streaming the body ------------------- +:: Streaming the body You can stream the request body by chunks. @@ -102,8 +97,7 @@ body_to_console(Req) -> You can of course set the `length` option to configure the size of chunks. -Rate of data transmission -------------------------- +:: Rate of data transmission You can control the rate of data transmission by setting options when calling body functions. This applies not only @@ -116,8 +110,7 @@ to be received from the socket at once, in bytes. The `read_timeout` option defines the time Cowboy waits before that amount is received, in milliseconds. -Transfer and content decoding ------------------------------ +:: Transfer and content decoding Cowboy will by default decode the chunked transfer-encoding if any. It will not decode any content-encoding by default. @@ -136,8 +129,7 @@ The following example shows how to set both options. ]). ``` -Reading a form urlencoded body ------------------------------- +:: Reading a form urlencoded body You can directly obtain a list of key/value pairs if the body was sent using the application/x-www-form-urlencoded diff --git a/guide/resource_design.md b/doc/src/guide/resource_design.ezdoc similarity index 93% rename from guide/resource_design.md rename to doc/src/guide/resource_design.ezdoc index 744e4eef..67cb09b3 100644 --- a/guide/resource_design.md +++ b/doc/src/guide/resource_design.ezdoc @@ -1,12 +1,10 @@ -Designing a resource handler -============================ +::: Designing a resource handler This chapter aims to provide you with a list of questions you must answer in order to write a good resource handler. It is meant to be usable as a step by step guide. -The service ------------ +:: The service Can the service become unavailable, and when it does, can we detect it? For example database connectivity problems @@ -19,8 +17,7 @@ more than the standard OPTIONS, HEAD, GET, PUT, POST, PATCH and DELETE? Are we not using one of those at all? Implement the `known_methods` callback. -Type of resource handler ------------------------- +:: Type of resource handler Am I writing a handler for a collection of resources, or for a single resource? @@ -29,8 +26,7 @@ The semantics for each of these are quite different. You should not mix collection and single resource in the same handler. -Collection handler ------------------- +:: Collection handler Skip this section if you are not doing a collection. @@ -74,8 +70,7 @@ operation is atomic. The PATCH operation may be used for such things as reordering; adding, modifying or deleting parts of the collection. -Single resource handler ------------------------ +:: Single resource handler Skip this section if you are doing a collection. @@ -103,8 +98,7 @@ operation is atomic. The PATCH operation may be used for adding, removing or modifying specific values in the resource. -The resource ------------- +:: The resource Following the above discussion, implement the `allowed_methods` callback. @@ -131,8 +125,7 @@ Is there any constraints on the length of the resource URI? For example the URI may be used as a key in storage and may have a limit in length. Implement `uri_too_long`. -Representations ---------------- +:: Representations What media types do I provide? If text based, what charsets are provided? What languages do I provide? @@ -156,8 +149,7 @@ representation available? Send a list of available representations in the response body and implement the `multiple_choices` callback. -Redirections ------------- +:: Redirections Do I need to keep track of what resources were deleted? For example you may have a mechanism where moving a @@ -169,8 +161,7 @@ it is explicitly temporary, for example due to maintenance, implement the `moved_temporarily` callback. Otherwise, implement the `moved_permanently` callback. -The request ------------ +:: The request Do we need to perform extra checks to make sure the request is valid? Cowboy will do many checks when receiving the @@ -185,23 +176,20 @@ to accept? Implement `valid_entity_length`. Finally, take a look at the sections corresponding to the methods you are implementing. -OPTIONS method --------------- +:: OPTIONS method Cowboy by default will send back a list of allowed methods. Do I need to add more information to the response? Implement the `options` method. -GET and HEAD methods --------------------- +:: GET and HEAD methods If you implement the methods GET and/or HEAD, you must implement one `ProvideResource` callback for each content-type returned by the `content_types_provided` callback. -PUT, POST and PATCH methods ---------------------------- +:: PUT, POST and PATCH methods If you implement the methods PUT, POST and/or PATCH, you must implement the `content_types_accepted` callback, @@ -220,8 +208,7 @@ a resource? Do we want to make sure that two updates around the same time are not cancelling one another? Implement the `is_conflict` callback. -DELETE methods --------------- +:: DELETE methods If you implement the method DELETE, you must implement the `delete_resource` callback. diff --git a/guide/resp.md b/doc/src/guide/resp.ezdoc similarity index 96% rename from guide/resp.md rename to doc/src/guide/resp.ezdoc index b3da72d1..28f25447 100644 --- a/guide/resp.md +++ b/doc/src/guide/resp.ezdoc @@ -1,5 +1,4 @@ -Sending a response -================== +::: Sending a response The Req object also allows you to send a response. @@ -10,8 +9,7 @@ with its body streamed by chunks of arbitrary size. You can also set headers or the response body in advance and Cowboy will use them when you finally do reply. -Reply ------ +:: Reply You can send a reply with no particular headers or body. Cowboy will make sure to send the mandatory headers with @@ -66,8 +64,7 @@ Here is the same example but sending HTML this time. Note that the reply is sent immediately. -Chunked reply -------------- +:: Chunked reply You can also stream the response body. First, you need to initiate the reply by sending the response status code. @@ -98,8 +95,7 @@ ok = cowboy_req:chunk("
Hats off!