mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 04:10:24 +00:00
Partial update of the user guide
I will do more breaking changes before documenting more.
This commit is contained in:
parent
25912dfc05
commit
b5a40256dd
9 changed files with 199 additions and 273 deletions
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
= Cowboy User Guide
|
= Cowboy User Guide
|
||||||
|
|
||||||
|
// REST: where should i handle bindings? init, probably. qs? in media type functions
|
||||||
|
// REST: explain how a module per media type is good; module may be shared between client/server
|
||||||
|
|
||||||
|
// @todo Put the list of RFCs and other documents supported somewhere.
|
||||||
|
|
||||||
= Rationale
|
= Rationale
|
||||||
|
|
||||||
include::modern_web.asciidoc[The modern Web]
|
include::modern_web.asciidoc[The modern Web]
|
||||||
|
@ -15,25 +20,31 @@ include::introduction.asciidoc[Introduction]
|
||||||
|
|
||||||
include::getting_started.asciidoc[Getting started]
|
include::getting_started.asciidoc[Getting started]
|
||||||
|
|
||||||
include::overview.asciidoc[Request overview]
|
// NEW! Flow diagram here
|
||||||
|
// MERGE include::overview.asciidoc[Request overview]
|
||||||
include::erlang_beginners.asciidoc[Erlang for beginners]
|
include::flow_diagram.asciidoc[Flow diagram]
|
||||||
|
|
||||||
= Configuration
|
= Configuration
|
||||||
|
|
||||||
include::routing.asciidoc[routing]
|
include::listeners.asciidoc[Listeners]
|
||||||
|
|
||||||
|
include::streams.asciidoc[Streams]
|
||||||
|
|
||||||
|
include::routing.asciidoc[Routing]
|
||||||
|
|
||||||
include::constraints.asciidoc[Constraints]
|
include::constraints.asciidoc[Constraints]
|
||||||
|
|
||||||
include::static_files.asciidoc[Static files]
|
= Handlers
|
||||||
|
|
||||||
= Request and response
|
|
||||||
|
|
||||||
include::handlers.asciidoc[Handlers]
|
include::handlers.asciidoc[Handlers]
|
||||||
|
|
||||||
include::loop_handlers.asciidoc[Loop handlers]
|
include::loop_handlers.asciidoc[Loop handlers]
|
||||||
|
|
||||||
include::req.asciidoc[The Req object]
|
include::static_files.asciidoc[Static files]
|
||||||
|
|
||||||
|
= Request and response
|
||||||
|
|
||||||
|
include::req.asciidoc[Request details]
|
||||||
|
|
||||||
include::req_body.asciidoc[Reading the request body]
|
include::req_body.asciidoc[Reading the request body]
|
||||||
|
|
||||||
|
@ -61,12 +72,15 @@ include::ws_handlers.asciidoc[Handling Websocket connections]
|
||||||
|
|
||||||
= Internals
|
= Internals
|
||||||
|
|
||||||
|
// TODO: shouldn't be needed anymore?
|
||||||
include::architecture.asciidoc[Architecture]
|
include::architecture.asciidoc[Architecture]
|
||||||
|
|
||||||
|
// TODO: Move into Common scenarios or something; switch to streams
|
||||||
include::broken_clients.asciidoc[Dealing with broken clients]
|
include::broken_clients.asciidoc[Dealing with broken clients]
|
||||||
|
|
||||||
include::middlewares.asciidoc[Middlewares]
|
include::middlewares.asciidoc[Middlewares]
|
||||||
|
|
||||||
include::sub_protocols.asciidoc[Sub protocols]
|
include::sub_protocols.asciidoc[Sub protocols]
|
||||||
|
|
||||||
|
// TODO: they're gone
|
||||||
include::hooks.asciidoc[Hooks]
|
include::hooks.asciidoc[Hooks]
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
[[erlang_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
|
|
||||||
chapter will help you get started.
|
|
||||||
|
|
||||||
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!
|
|
||||||
|
|
||||||
The quickest way to get started with Erlang is by reading
|
|
||||||
a book with the funny name of http://learnyousomeerlang.com[LYSE],
|
|
||||||
as we affectionately call it.
|
|
||||||
|
|
||||||
It will get right into the syntax and quickly answer the questions
|
|
||||||
a beginner would ask themselves, all the while showing funny
|
|
||||||
pictures and making insightful jokes.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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 http://pragprog.com/book/jaerlang2/programming-erlang[Programming Erlang].
|
|
||||||
|
|
||||||
Instead of going into every single details of the language,
|
|
||||||
Joe focuses on the central concepts behind Erlang, and shows
|
|
||||||
you how they can be used to write a variety of different
|
|
||||||
applications.
|
|
|
@ -1,6 +1,10 @@
|
||||||
[[erlang_web]]
|
[[erlang_web]]
|
||||||
== Erlang and the Web
|
== Erlang and the Web
|
||||||
|
|
||||||
|
Erlang is the ideal platform for writing Web applications.
|
||||||
|
Its features are a perfect match for the requirements of
|
||||||
|
modern Web applications.
|
||||||
|
|
||||||
=== The Web is concurrent
|
=== The Web is concurrent
|
||||||
|
|
||||||
When you access a website there is little concurrency
|
When you access a website there is little concurrency
|
||||||
|
@ -130,7 +134,7 @@ their applications to be always available and if it's having
|
||||||
too many issues they just move on.
|
too many issues they just move on.
|
||||||
|
|
||||||
Despite this, when developers choose a product to use for building
|
Despite this, when developers choose a product to use for building
|
||||||
web applications, their only concern seem to be "Is it fast?",
|
web applications, their only concern seems to be "Is it fast?",
|
||||||
and they look around for synthetic benchmarks showing which one
|
and they look around for synthetic benchmarks showing which one
|
||||||
is the fastest at sending "Hello world" with only a handful
|
is the fastest at sending "Hello world" with only a handful
|
||||||
concurrent connections. Web benchmarks haven't been representative
|
concurrent connections. Web benchmarks haven't been representative
|
||||||
|
@ -146,15 +150,15 @@ Erlang is built for fault tolerance. When writing code in any other
|
||||||
language, you have to check all the return values and act accordingly
|
language, you have to check all the return values and act accordingly
|
||||||
to avoid any unforeseen issues. If you're lucky, you won't miss
|
to avoid any unforeseen issues. If you're lucky, you won't miss
|
||||||
anything important. When writing Erlang code, you can just check
|
anything important. When writing Erlang code, you can just check
|
||||||
the success condition and ignore all errors. If an error happen,
|
the success condition and ignore all errors. If an error happens,
|
||||||
the Erlang process crashes and is then restarted by a special
|
the Erlang process crashes and is then restarted by a special
|
||||||
process called a supervisor.
|
process called a supervisor.
|
||||||
|
|
||||||
The Erlang developer thus has no need to fear about unhandled
|
Erlang developers thus have no need to fear unhandled
|
||||||
errors, and can focus on handling only the errors that should
|
errors, and can focus on handling only the errors that should
|
||||||
give some feedback to the user and let the system take care of
|
give some feedback to the user and let the system take care of
|
||||||
the rest. This also has the advantage of allowing him to write
|
the rest. This also has the advantage of allowing them to write
|
||||||
a lot less code, and letting him sleep at night.
|
a lot less code, and let them sleep at night.
|
||||||
|
|
||||||
Erlang's fault tolerance oriented design is the first piece of
|
Erlang's fault tolerance oriented design is the first piece of
|
||||||
what makes it the best choice for the omnipresent, always available
|
what makes it the best choice for the omnipresent, always available
|
||||||
|
@ -168,9 +172,38 @@ down, or even a data center entirely.
|
||||||
Fault tolerance and distribution are important today, and will be
|
Fault tolerance and distribution are important today, and will be
|
||||||
vital in the future of the Web. Erlang is ready.
|
vital in the future of the Web. Erlang is ready.
|
||||||
|
|
||||||
=== Erlang is the ideal platform for the Web
|
=== Learn Erlang
|
||||||
|
|
||||||
Erlang provides all the important features that the Web requires
|
If you are new to Erlang, you may want to grab a book or
|
||||||
or will require in the near future. Erlang is a perfect match
|
two to get started. Those are my recommendations as the
|
||||||
for the Web, and it only makes sense to use it to build web
|
author of Cowboy.
|
||||||
applications.
|
|
||||||
|
==== The Erlanger Playbook
|
||||||
|
|
||||||
|
The Erlanger Playbook is an ebook I am currently writing,
|
||||||
|
which covers a number of different topics from code to
|
||||||
|
documentation to testing Erlang applications. It also has
|
||||||
|
an Erlang section where it covers directly the building
|
||||||
|
blocks and patterns, rather than details like the syntax.
|
||||||
|
|
||||||
|
You can most likely read it as a complete beginner, but
|
||||||
|
you will need a companion book to make the most of it.
|
||||||
|
Buy it from the http://ninenines.eu[Nine Nines website].
|
||||||
|
|
||||||
|
==== Programming Erlang
|
||||||
|
|
||||||
|
This book is from one of the creator of Erlang, Joe
|
||||||
|
Armstrong. It provides a very good explanation of what
|
||||||
|
Erlang is and why it is so. It serves as a very good
|
||||||
|
introduction to the language and platform.
|
||||||
|
|
||||||
|
The book is http://pragprog.com/book/jaerlang2/programming-erlang[Programming Erlang],
|
||||||
|
and it also features a chapter on Cowboy.
|
||||||
|
|
||||||
|
==== Learn You Some Erlang for Great Good!
|
||||||
|
|
||||||
|
http://learnyousomeerlang.com[LYSE] is a much more complete
|
||||||
|
book covering many aspects of Erlang, while also providing
|
||||||
|
stories and humor. Be warned: it's pretty verbose. It comes
|
||||||
|
with a free online version and a more refined paper and
|
||||||
|
ebook version.
|
||||||
|
|
|
@ -13,11 +13,14 @@ 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.
|
||||||
|
|
||||||
=== Bootstrap
|
=== Prerequisites
|
||||||
|
|
||||||
We are going to use the https://github.com/ninenines/erlang.mk[Erlang.mk]
|
We are going to use the https://github.com/ninenines/erlang.mk[Erlang.mk]
|
||||||
build system. It also offers bootstrap features allowing us to
|
build system. If you are using Windows, please check the
|
||||||
quickly get started without having to deal with minute details.
|
http://erlang.mk/guide/installation.html[Installation instructions]
|
||||||
|
to get your environment setup before you continue.
|
||||||
|
|
||||||
|
=== Bootstrap
|
||||||
|
|
||||||
First, let's create the directory for our application.
|
First, let's create the directory for our application.
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ Then we need to download Erlang.mk. Either use the following
|
||||||
command or download it manually.
|
command or download it manually.
|
||||||
|
|
||||||
[source,bash]
|
[source,bash]
|
||||||
$ wget https://raw.githubusercontent.com/ninenines/erlang.mk/master/erlang.mk
|
$ wget https://erlang.mk/erlang.mk
|
||||||
|
|
||||||
We can now bootstrap our application. Since we are going to generate
|
We can now bootstrap our application. Since we are going to generate
|
||||||
a release, we will also bootstrap it at the same time.
|
a release, we will also bootstrap it at the same time.
|
||||||
|
@ -58,9 +61,8 @@ handler.
|
||||||
|
|
||||||
=== Cowboy setup
|
=== Cowboy setup
|
||||||
|
|
||||||
Modifying the 'Makefile' allows the build system to know it needs to
|
We will modify the 'Makefile' to tell the build system it needs to
|
||||||
fetch and compile Cowboy. To do that we simply need to add two lines
|
fetch and compile Cowboy:
|
||||||
to our Makefile to make it look like this:
|
|
||||||
|
|
||||||
[source,make]
|
[source,make]
|
||||||
----
|
----
|
||||||
|
@ -79,10 +81,9 @@ listen for connections.
|
||||||
|
|
||||||
=== Listening for connections
|
=== Listening for connections
|
||||||
|
|
||||||
We will do this when our application starts. It's a two step process.
|
First we define the routes that Cowboy will use to map requests
|
||||||
First we need to define and compile the dispatch list, a list of
|
to handler modules, and then we start the listener. This is best
|
||||||
routes that Cowboy will use to map requests to handler modules.
|
done at application startup.
|
||||||
Then we tell Cowboy to listen for connections.
|
|
||||||
|
|
||||||
Open the 'src/hello_erlang_app.erl' file and add the necessary
|
Open the 'src/hello_erlang_app.erl' file and add the necessary
|
||||||
code to the `start/2` function to make it look like this:
|
code to the `start/2` function to make it look like this:
|
||||||
|
@ -93,19 +94,19 @@ start(_Type, _Args) ->
|
||||||
Dispatch = cowboy_router:compile([
|
Dispatch = cowboy_router:compile([
|
||||||
{'_', [{"/", hello_handler, []}]}
|
{'_', [{"/", hello_handler, []}]}
|
||||||
]),
|
]),
|
||||||
{ok, _} = cowboy:start_http(my_http_listener, 100, [{port, 8080}],
|
{ok, _} = cowboy:start_clear(my_http_listener, 100,
|
||||||
[{env, [{dispatch, Dispatch}]}]
|
[{port, 8080}],
|
||||||
|
#{env => #{dispatch => Dispatch}}
|
||||||
),
|
),
|
||||||
hello_erlang_sup:start_link().
|
hello_erlang_sup:start_link().
|
||||||
----
|
----
|
||||||
|
|
||||||
The dispatch list is explained in great details in the
|
Routes are explained in details in the xref:routing[Routing]
|
||||||
xref:routing[Routing] chapter. For this tutorial we map the
|
chapter. For this tutorial we map the path `/` to the handler
|
||||||
path `/` to the handler module `hello_handler`. This module
|
module `hello_handler`. This module doesn't exist yet.
|
||||||
doesn't exist yet, we still have to write it.
|
|
||||||
|
|
||||||
If you build and start the release, then open http://localhost:8080
|
Build and start the release, then open http://localhost:8080
|
||||||
in your browser, you will get an error because the module is missing.
|
in your browser. You will get an error because the module is missing.
|
||||||
Any other URL, like http://localhost:8080/test, will result in a
|
Any other URL, like http://localhost:8080/test, will result in a
|
||||||
404 error.
|
404 error.
|
||||||
|
|
||||||
|
@ -115,26 +116,26 @@ Cowboy features different kinds of handlers, including REST
|
||||||
and Websocket handlers. For this tutorial we will use a plain
|
and Websocket handlers. For this tutorial we will use a plain
|
||||||
HTTP handler.
|
HTTP handler.
|
||||||
|
|
||||||
First, let's generate a handler from a template.
|
Generate a handler from a template:
|
||||||
|
|
||||||
[source,bash]
|
[source,bash]
|
||||||
$ make new t=cowboy_http n=hello_handler
|
$ make new t=cowboy_http n=hello_handler
|
||||||
|
|
||||||
You can then open the 'src/hello_handler.erl' file and modify
|
Then, open the 'src/hello_handler.erl' file and modify
|
||||||
the `init/2` function like this to send a reply.
|
the `init/2` function like this to send a reply.
|
||||||
|
|
||||||
[source,erlang]
|
[source,erlang]
|
||||||
----
|
----
|
||||||
init(Req, Opts) ->
|
init(Req, State) ->
|
||||||
Req2 = cowboy_req:reply(200,
|
cowboy_req:reply(200,
|
||||||
[{<<"content-type">>, <<"text/plain">>}],
|
#{<<"content-type">> => <<"text/plain">>},
|
||||||
<<"Hello Erlang!">>,
|
<<"Hello Erlang!">>,
|
||||||
Req),
|
Req),
|
||||||
{ok, Req2, Opts}.
|
{ok, Req, State}.
|
||||||
----
|
----
|
||||||
|
|
||||||
What the above code does is send a `200 OK` reply, with the
|
What the above code does is send a `200 OK` reply, with the
|
||||||
`content-type` header set to `text/plain` and the response
|
Content-type header set to `text/plain` and the response
|
||||||
body set to `Hello Erlang!`.
|
body set to `Hello Erlang!`.
|
||||||
|
|
||||||
If you run the release and open http://localhost:8080
|
If you run the release and open http://localhost:8080
|
||||||
|
|
|
@ -28,18 +28,16 @@ We need to use the Req object for sending a reply.
|
||||||
|
|
||||||
[source,erlang]
|
[source,erlang]
|
||||||
----
|
----
|
||||||
init(Req, _Opts) ->
|
init(Req, State) ->
|
||||||
Req2 = cowboy_req:reply(200, [
|
cowboy_req:reply(200, [
|
||||||
{<<"content-type">>, <<"text/plain">>}
|
{<<"content-type">>, <<"text/plain">>}
|
||||||
], <<"Hello World!">>, Req),
|
], <<"Hello World!">>, Req),
|
||||||
{ok, Req2, #state{}}.
|
{ok, Req, State}.
|
||||||
----
|
----
|
||||||
|
|
||||||
As you can see we return a 3-tuple. `ok` means that the
|
As you can see we return a 3-tuple. `ok` means that the
|
||||||
handler ran successfully. The Req object is returned as
|
handler ran successfully. Note that Cowboy will immediately
|
||||||
it may have been modified as is the case here: replying
|
send a response when `cowboy:reply/4` is called.
|
||||||
returns a modified Req object that you need to return
|
|
||||||
back to Cowboy for proper operations.
|
|
||||||
|
|
||||||
The last value of the tuple is a state that will be used
|
The last value of the tuple is a state that will be used
|
||||||
in every subsequent callbacks to this handler. Plain HTTP
|
in every subsequent callbacks to this handler. Plain HTTP
|
||||||
|
@ -94,12 +92,8 @@ This callback is strictly reserved for any required cleanup.
|
||||||
You cannot send a response from this function. There is no
|
You cannot send a response from this function. There is no
|
||||||
other return value.
|
other return value.
|
||||||
|
|
||||||
If you used the process dictionary, timers, monitors or may
|
This callback is optional because it is rarely necessary.
|
||||||
be receiving messages, then you can use this function to clean
|
Cleanup should be done in separate processes directly (by
|
||||||
them up, as Cowboy might reuse the process for the next
|
monitoring the handler process to detect when it exits).
|
||||||
keep-alive request.
|
|
||||||
|
|
||||||
Note that while this function may be called in a Websocket
|
Cowboy does not reuse processes for different requests.
|
||||||
handler, it is generally not useful to do any clean up as
|
|
||||||
the process terminates immediately after calling this callback
|
|
||||||
when using Websocket.
|
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
|
|
||||||
Cowboy is a small, fast and modular HTTP server written in Erlang.
|
Cowboy is a small, fast and modular HTTP server written in Erlang.
|
||||||
|
|
||||||
Cowboy aims to provide a complete HTTP stack, including its derivatives
|
Cowboy aims to provide a complete xref:modern_web[modern Web stack].
|
||||||
Websocket and REST. Cowboy currently supports HTTP/1.0, HTTP/1.1, HTTP/2,
|
This includes HTTP/1.1, HTTP/2, Websocket, Server-Sent Events and
|
||||||
Websocket (all implemented drafts + standard) and Webmachine-based REST.
|
Webmachine-based REST.
|
||||||
|
|
||||||
|
Cowboy comes with functions for introspection and tracing, enabling
|
||||||
|
developers to know precisely what is happening at any time. Its modular
|
||||||
|
design also easily enable developers to add instrumentation.
|
||||||
|
|
||||||
Cowboy is a high quality project. It has a small code base, is very
|
Cowboy is a high quality project. It has a small code base, is very
|
||||||
efficient (both in latency and memory use) and can easily be embedded
|
efficient (both in latency and memory use) and can easily be embedded
|
||||||
|
@ -13,7 +17,7 @@ in another application.
|
||||||
|
|
||||||
Cowboy is clean Erlang code. It includes hundreds of tests and its code
|
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
|
is fully compliant with the Dialyzer. It is also well documented and
|
||||||
features both a Function Reference and a User Guide.
|
features a Function Reference, a User Guide and numerous Tutorials.
|
||||||
|
|
||||||
=== Prerequisites
|
=== Prerequisites
|
||||||
|
|
||||||
|
@ -24,21 +28,14 @@ will be detailed throughout the guide.
|
||||||
|
|
||||||
=== Supported platforms
|
=== Supported platforms
|
||||||
|
|
||||||
Cowboy is tested and supported on Linux.
|
Cowboy is tested and supported on Linux, FreeBSD, Windows and OSX.
|
||||||
|
|
||||||
Cowboy has been reported to work on other platforms, but we make no
|
Cowboy has been reported to work on other platforms, but we make no
|
||||||
guarantee that the experience will be safe and smooth. You are advised
|
guarantee that the experience will be safe and smooth. You are advised
|
||||||
to perform the necessary testing and security audits prior to deploying
|
to perform the necessary testing and security audits prior to deploying
|
||||||
on other platforms.
|
on other platforms.
|
||||||
|
|
||||||
Cowboy is developed for Erlang/OTP 17.0, 17.1.2 and 17.3. By the time
|
Cowboy is developed for Erlang/OTP 18.0 and newer.
|
||||||
this branch gets released the target version will probably be 18.0 and
|
|
||||||
above.
|
|
||||||
|
|
||||||
Cowboy may be compiled on other Erlang versions with small source code
|
|
||||||
modifications but there is no guarantee that it will work as expected.
|
|
||||||
|
|
||||||
Cowboy uses the maps data type which was introduced in Erlang 17.0.
|
|
||||||
|
|
||||||
=== Versioning
|
=== Versioning
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
[[loop_handlers]]
|
[[loop_handlers]]
|
||||||
== Loop handlers
|
== Loop handlers
|
||||||
|
|
||||||
|
// @todo This description needs to be updated.
|
||||||
|
|
||||||
Loop handlers are a special kind of HTTP handlers used when the
|
Loop handlers are a special kind of HTTP handlers used when the
|
||||||
response can not be sent right away. The handler enters instead
|
response can not be sent right away. The handler enters instead
|
||||||
a receive loop waiting for the right message before it can send
|
a receive loop waiting for the right message before it can send
|
||||||
|
@ -64,8 +66,8 @@ message otherwise.
|
||||||
[source,erlang]
|
[source,erlang]
|
||||||
----
|
----
|
||||||
info({reply, Body}, Req, State) ->
|
info({reply, Body}, Req, State) ->
|
||||||
Req2 = cowboy_req:reply(200, [], Body, Req),
|
cowboy_req:reply(200, [], Body, Req),
|
||||||
{stop, Req2, State};
|
{stop, Req, State};
|
||||||
info(_Msg, Req, State) ->
|
info(_Msg, Req, State) ->
|
||||||
{ok, Req, State, hibernate}.
|
{ok, Req, State, hibernate}.
|
||||||
----
|
----
|
||||||
|
|
|
@ -1,164 +1,58 @@
|
||||||
[[modern_web]]
|
[[modern_web]]
|
||||||
== The modern Web
|
== The modern Web
|
||||||
|
|
||||||
Let's take a look at various technologies from the beginnings
|
// @todo Link to related xrefs.
|
||||||
of the Web up to this day, and get a preview of what's
|
|
||||||
coming next.
|
|
||||||
|
|
||||||
Cowboy is compatible with all the technology cited in this
|
Cowboy is a server for the modern Web. This chapter explains
|
||||||
chapter except of course HTTP/2.0 which has no implementation
|
what it means and details all the standards involved.
|
||||||
in the wild at the time of writing.
|
|
||||||
|
|
||||||
=== The prehistoric Web
|
Cowboy supports all the standards listed in this document.
|
||||||
|
|
||||||
HTTP was initially created to serve HTML pages and only
|
=== HTTP/2
|
||||||
had the GET method for retrieving them. This initial
|
|
||||||
version is documented and is sometimes called HTTP/0.9.
|
|
||||||
HTTP/1.0 defined the GET, HEAD and POST methods, and
|
|
||||||
was able to send data with POST requests.
|
|
||||||
|
|
||||||
HTTP/1.0 works in a very simple way. A TCP connection
|
HTTP/2 is the most efficient protocol for consuming Web
|
||||||
is first established to the server. Then a request is
|
services. It enables clients to keep a connection open
|
||||||
sent. Then the server sends a response back and closes
|
for long periods of time; to send requests concurrently;
|
||||||
the connection.
|
to reduce the size of requests through HTTP headers
|
||||||
|
compression; and more. The protocol is binary, greatly
|
||||||
|
reducing the resources needed to parse it.
|
||||||
|
|
||||||
Suffice to say, HTTP/1.0 is not very efficient. Opening
|
HTTP/2 also enables the server to push messages to the
|
||||||
a TCP connection takes some time, and pages containing
|
client. This can be used for various purposes, including
|
||||||
many assets load much slower than they could because of
|
the sending of related resources before the client requests
|
||||||
this.
|
them, in an effort to reduce latency. This can also be used
|
||||||
|
to enable bidirectional communication.
|
||||||
|
|
||||||
Most improvements done in recent years focused on reducing
|
Cowboy provides transparent support for HTTP/2. Clients
|
||||||
this load time and reducing the latency of the requests.
|
that know it can use it; others fall back to HTTP/1.1
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
HTTP/2 is compatible with the HTTP/1.1 semantics.
|
||||||
|
|
||||||
|
HTTP/2 is defined by RFC 7540 and RFC 7541.
|
||||||
|
|
||||||
=== HTTP/1.1
|
=== HTTP/1.1
|
||||||
|
|
||||||
HTTP/1.1 quickly followed and added a keep-alive mechanism
|
HTTP/1.1 is the previous version of the HTTP protocol.
|
||||||
to allow using the same connection for many requests, as
|
The protocol itself is text-based and suffers from numerous
|
||||||
well as streaming capabilities, allowing an endpoint to send
|
issues and limitations. In particular it is not possible
|
||||||
a body in well defined chunks.
|
to execute requests concurrently (though pipelining is
|
||||||
|
sometimes possible), and it's also sometimes difficult
|
||||||
|
to detect that a client disconnected.
|
||||||
|
|
||||||
HTTP/1.1 defines the OPTIONS, GET, HEAD, POST, PUT, DELETE,
|
HTTP/1.1 does provide very good semantics for interacting
|
||||||
TRACE and CONNECT methods. The PATCH method was added in more
|
with Web services. It defines the standard methods, headers
|
||||||
recent years. It also improves the caching capabilities with
|
and status codes used by HTTP/1.1 and HTTP/2 clients and
|
||||||
the introduction of many headers.
|
servers.
|
||||||
|
|
||||||
HTTP/1.1 still works like HTTP/1.0 does, except the connection
|
HTTP/1.1 also defines compatibility with an older version
|
||||||
can be kept alive for subsequent requests. This however allows
|
of the protocol, HTTP/1.0, which was never really standardized
|
||||||
clients to perform what is called as pipelining: sending many
|
across implementations.
|
||||||
requests in a row, and then processing the responses which will
|
|
||||||
be received in the same order as the requests.
|
|
||||||
|
|
||||||
=== REST
|
The core of HTTP/1.1 is defined by RFC 7230, RFC 7231,
|
||||||
|
RFC 7232, RFC 7233, RFC 7234 and RFC 7235. Numerous RFCs
|
||||||
The design of HTTP/1.1 was influenced by the REST architectural
|
and other specifications exist defining additional HTTP
|
||||||
style. REST, or REpresentational State Transfer, is a style of
|
methods, status codes, headers or semantics.
|
||||||
architecture for loosely connected distributed systems.
|
|
||||||
|
|
||||||
REST defines constraints that systems must obey to in order to
|
|
||||||
be RESTful. A system which doesn't follow all the constraints
|
|
||||||
cannot be considered RESTful.
|
|
||||||
|
|
||||||
REST is a client-server architecture with a clean separation
|
|
||||||
of concerns between the client and the server. They communicate
|
|
||||||
by referencing resources. Resources can be identified, but
|
|
||||||
also manipulated. A resource representation has a media type
|
|
||||||
and information about whether it can be cached and how. Hypermedia
|
|
||||||
determines how resources are related and how they can be used.
|
|
||||||
REST is also stateless. All requests contain the complete
|
|
||||||
information necessary to perform the action.
|
|
||||||
|
|
||||||
HTTP/1.1 defines all the methods, headers and semantics required
|
|
||||||
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
|
|
||||||
|
|
||||||
Also know as AJAX, this technology allows Javascript code running
|
|
||||||
on a web page to perform asynchronous requests to the server.
|
|
||||||
This is what started the move from static websites to dynamic
|
|
||||||
web applications.
|
|
||||||
|
|
||||||
XmlHttpRequest still performs HTTP requests under the hood,
|
|
||||||
and then waits for a response, but the Javascript code can
|
|
||||||
continue to run until the response arrives. It will then receive
|
|
||||||
the response through a callback previously defined.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
Polling was a technique used to overcome the fact that the server
|
|
||||||
cannot push data directly to the client. Therefore the client had
|
|
||||||
to repeatedly create a connection, make a request, get a response,
|
|
||||||
then try again a few seconds later. This is overly expensive and
|
|
||||||
adds an additional delay before the client receives the data.
|
|
||||||
|
|
||||||
Polling was necessary to implement message queues and other
|
|
||||||
similar mechanisms, where a user must be informed of something
|
|
||||||
when it happens, rather than when he refreshes the page next.
|
|
||||||
A typical example would be a chat application.
|
|
||||||
|
|
||||||
Long-polling was created to reduce the server load by creating
|
|
||||||
less connections, but also to improve latency by getting the
|
|
||||||
response back to the client as soon as it becomes available
|
|
||||||
on the server.
|
|
||||||
|
|
||||||
Long-polling works in a similar manner to polling, except the
|
|
||||||
request will not get a response immediately. Instead the server
|
|
||||||
leaves it open until it has a response to send. After getting
|
|
||||||
the response, the client creates a new request and gets back
|
|
||||||
to waiting.
|
|
||||||
|
|
||||||
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 is, of course, the HTML version after HTML4. But HTML5
|
|
||||||
emerged to solve a specific problem: dynamic web applications.
|
|
||||||
|
|
||||||
HTML was initially created to write web pages which compose
|
|
||||||
a website. But soon people and companies wanted to use HTML
|
|
||||||
to write more and more complex websites, eventually known as
|
|
||||||
web applications. They are for example your news reader, your
|
|
||||||
email client in the browser, or your video streaming website.
|
|
||||||
|
|
||||||
Because HTML wasn't enough, they started using proprietary
|
|
||||||
solutions, often implemented using plug-ins. This wasn't
|
|
||||||
perfect of course, but worked well enough for most people.
|
|
||||||
|
|
||||||
However, the needs for a standard solution eventually became
|
|
||||||
apparent. The browser needed to be able to play media natively.
|
|
||||||
It needed to be able to draw anything. It needed an efficient
|
|
||||||
way of streaming events to the server, but also receiving
|
|
||||||
events from the server.
|
|
||||||
|
|
||||||
The solution went on to become HTML5. At the time of writing
|
|
||||||
it is being standardized.
|
|
||||||
|
|
||||||
=== EventSource
|
|
||||||
|
|
||||||
EventSource, sometimes also called Server-Sent Events, is a
|
|
||||||
technology allowing servers to push data to HTML5 applications.
|
|
||||||
|
|
||||||
EventSource is one-way communication channel from the server
|
|
||||||
to the client. The client has no means to talk to the server
|
|
||||||
other than by using HTTP requests.
|
|
||||||
|
|
||||||
It consists of a Javascript object allowing setting up an
|
|
||||||
EventSource connection to the server, and a very small protocol
|
|
||||||
for sending events to the client on top of the HTTP/1.1
|
|
||||||
connection.
|
|
||||||
|
|
||||||
EventSource is a lightweight solution that only works for
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -180,21 +74,48 @@ A Websocket connection can be used to transfer any kind of data,
|
||||||
small or big, text or binary. Because of this Websocket is
|
small or big, text or binary. Because of this Websocket is
|
||||||
sometimes used for communication between systems.
|
sometimes used for communication between systems.
|
||||||
|
|
||||||
=== HTTP/2
|
Websocket messages have no semantics on their own. Websocket
|
||||||
|
is closer to TCP in that aspect, and requires you to design
|
||||||
|
and implement your own protocol on top of it; or adapt an
|
||||||
|
existing protocol to Websocket.
|
||||||
|
|
||||||
HTTP/2 is an attempt to reduce page loading time by opening a
|
The Websocket protocol is defined by RFC 6455.
|
||||||
single connection per server, keeping it open for subsequent
|
|
||||||
requests, and also by compressing the HTTP headers to reduce
|
|
||||||
the size of requests.
|
|
||||||
|
|
||||||
HTTP/2 is compatible with HTTP/1.1 semantics, and is actually
|
=== Long-lived requests
|
||||||
just a different way of performing HTTP requests and responses,
|
|
||||||
by using binary frames instead of a text-based protocol.
|
|
||||||
HTTP/2 also allows the server to send extra responses following
|
|
||||||
a request. This is meant to allow sending the resources
|
|
||||||
associated with the request before the client requests them,
|
|
||||||
saving latency when loading websites.
|
|
||||||
|
|
||||||
Browsers make use of TLS Application-Layer Protocol Negotiation
|
Cowboy provides an interface that can be used to support
|
||||||
extension to upgrade to an HTTP/2 connection seamlessly if the
|
long-polling or to stream large amounts of data reliably,
|
||||||
server supports it.
|
including using Server-Sent Events.
|
||||||
|
|
||||||
|
Long-polling is a mechanism in which the client performs
|
||||||
|
a request which may not be immediately answered by the
|
||||||
|
server. It allows clients to request resources that may
|
||||||
|
not currently exist, but are expected to be created soon,
|
||||||
|
and which will be returned as soon as they are.
|
||||||
|
|
||||||
|
Long-polling is essentially a hack, but it is widely used
|
||||||
|
to overcome limitations on older clients and servers.
|
||||||
|
|
||||||
|
Server-Sent Events is a small protocol defined as a media
|
||||||
|
type, `text/event-stream`, along with a new HTTP header,
|
||||||
|
`Last-Event-ID`. It is defined in the EventSource W3C
|
||||||
|
specification.
|
||||||
|
|
||||||
|
Cowboy provides an interface known as loop handlers that
|
||||||
|
facilitates the implementation of long-polling or stream
|
||||||
|
mechanisms. It works regardless of the underlying protocol.
|
||||||
|
|
||||||
|
=== REST
|
||||||
|
|
||||||
|
REST, or REpresentational State Transfer, is a style of
|
||||||
|
architecture for loosely connected distributed systems.
|
||||||
|
It can easily be implemented on top of HTTP.
|
||||||
|
|
||||||
|
REST is essentially a set of constraints to be followed.
|
||||||
|
Many of these constraints are purely architectural and
|
||||||
|
solved by simply using HTTP. Some constraints must be
|
||||||
|
explicitly followed by the developer.
|
||||||
|
|
||||||
|
Cowboy provides an interface known as REST handlers that
|
||||||
|
simplifies the implementation of a REST API on top of
|
||||||
|
the HTTP protocol.
|
||||||
|
|
|
@ -203,9 +203,9 @@ Dispatch = cowboy_router:compile([
|
||||||
{'_', [{'_', my_handler, []}]}
|
{'_', [{'_', my_handler, []}]}
|
||||||
]),
|
]),
|
||||||
%% Name, NbAcceptors, TransOpts, ProtoOpts
|
%% Name, NbAcceptors, TransOpts, ProtoOpts
|
||||||
cowboy:start_http(my_http_listener, 100,
|
cowboy:start_clear(my_http_listener, 100,
|
||||||
[{port, 8080}],
|
[{port, 8080}],
|
||||||
[{env, [{dispatch, Dispatch}]}]
|
#{env => #{dispatch => Dispatch}}
|
||||||
).
|
).
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue