Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 231 lines (177 sloc) 8.212 kB
da72255 Initial commit.
Loïc Hoguin authored
1 Cowboy
2 ======
3
4 Cowboy is a small, fast and modular HTTP server written in Erlang.
5
6 Goals
7 -----
8
9 Cowboy aims to provide the following advantages:
10
5a7b742 Greatly improve the README.
Loïc Hoguin authored
11 * **Small** code base.
da72255 Initial commit.
Loïc Hoguin authored
12 * Damn **fast**.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
13 * **Modular**: transport and protocol handlers are replaceable.
14 * **Binary HTTP** for greater speed and lower memory usage.
da72255 Initial commit.
Loïc Hoguin authored
15 * Easy to **embed** inside another application.
16 * Selectively **dispatch** requests to handlers, allowing you to send some
17 requests to your embedded code and others to a FastCGI application in
18 PHP or Ruby.
19 * No parameterized module. No process dictionary. **Clean** Erlang code.
20
548a9a1 README: Grammar fixes.
Loïc Hoguin authored
21 The server is currently in early development. Comments and suggestions are
da72255 Initial commit.
Loïc Hoguin authored
22 more than welcome. To contribute, either open bug reports, or fork the project
5a7b742 Greatly improve the README.
Loïc Hoguin authored
23 and send us pull requests with new or improved functionality. You should
24 discuss your plans with us before doing any serious work, though, to avoid
25 duplicating efforts.
da72255 Initial commit.
Loïc Hoguin authored
26
5a7b742 Greatly improve the README.
Loïc Hoguin authored
27 Quick start
28 -----------
da72255 Initial commit.
Loïc Hoguin authored
29
cf6a506 @yrashk README: added a mentioning of agner dependencies mechanism
yrashk authored
30 * Add Cowboy as a rebar or agner dependency to your application.
da72255 Initial commit.
Loïc Hoguin authored
31 * Start Cowboy and add one or more listeners.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
32 * Write handlers for your application.
e4124de @essen Switch to Ranch for connection handling
essen authored
33 * Check out the `examples/` directory!
da72255 Initial commit.
Loïc Hoguin authored
34
c4d4b6a Rename the title for Getting Started in the README.
Loïc Hoguin authored
35 Getting Started
36 ---------------
da72255 Initial commit.
Loïc Hoguin authored
37
e4124de @essen Switch to Ranch for connection handling
essen authored
38 Cowboy does nothing by default.
e4da695 Anonymize and improve the cowboy supervision tree.
Loïc Hoguin authored
39
e4124de @essen Switch to Ranch for connection handling
essen authored
40 Cowboy uses Ranch for handling connections, and provides convenience
41 functions to start and stop Ranch listeners. The Ranch application
42 must always be started before Cowboy.
da72255 Initial commit.
Loïc Hoguin authored
43
e4124de @essen Switch to Ranch for connection handling
essen authored
44 The `cowboy:start_http/4` function will handle HTTP connections
45 using the TCP transport. Similarly, `cowboy:start_https/4` will
46 handle HTTP connections using the SSL transport.
da72255 Initial commit.
Loïc Hoguin authored
47
e4124de @essen Switch to Ranch for connection handling
essen authored
48 You can start as many listeners as you need to. To allow this, you
49 are required to give a name to your listeners. It is the first
50 argument to the start functions. The name can be of any type.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
51
e4124de @essen Switch to Ranch for connection handling
essen authored
52 You can stop listeners using `cowboy:stop_listener/1`, giving it
53 the name of the listener to be stopped.
718baff Make Cowboy an OTP application again, properly this time.
Loïc Hoguin authored
54
e4124de @essen Switch to Ranch for connection handling
essen authored
55 The following example demonstrates the startup of a very simple
56 HTTP listener. It redirects all requests to the `my_handler`
57 module.
da72255 Initial commit.
Loïc Hoguin authored
58
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
59 ``` erlang
e4124de @essen Switch to Ranch for connection handling
essen authored
60 application:start(ranch),
39513de Removed a few lines from the README for pedantic correctness.
Loïc Hoguin authored
61 application:start(cowboy),
62 Dispatch = [
e4124de @essen Switch to Ranch for connection handling
essen authored
63 %% {URIHost, list({URIPath, Handler, Opts})}
39513de Removed a few lines from the README for pedantic correctness.
Loïc Hoguin authored
64 {'_', [{'_', my_handler, []}]}
65 ],
e4124de @essen Switch to Ranch for connection handling
essen authored
66 %% Name, NbAcceptors, TransOpts, ProtoOpts
67 cowboy:start_http(my_http_listener, 100, [{port, 8080}],
68 [{dispatch, Dispatch}]
39513de Removed a few lines from the README for pedantic correctness.
Loïc Hoguin authored
69 ).
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
70 ```
da72255 Initial commit.
Loïc Hoguin authored
71
e4124de @essen Switch to Ranch for connection handling
essen authored
72 This is not enough though, you must also write the `my_handler`
73 module to process the incoming HTTP requests. Of course Cowboy
74 comes with predefined handlers for specific tasks but most of
75 the time you'll need to write the handlers appropriate for your
76 application.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
77
cd73784 @nox Improve README
nox authored
78 Following is an example of a "Hello World!" HTTP handler.
da72255 Initial commit.
Loïc Hoguin authored
79
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
80 ``` erlang
81 -module(my_handler).
82 -export([init/3, handle/2, terminate/2]).
da72255 Initial commit.
Loïc Hoguin authored
83
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
84 init({tcp, http}, Req, Opts) ->
5a7b742 Greatly improve the README.
Loïc Hoguin authored
85 {ok, Req, undefined_state}.
f532355 Introduce Handler:init/2 for initializing the handler state.
Loïc Hoguin authored
86
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
87 handle(Req, State) ->
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
88 {ok, Req2} = cowboy_req:reply(200, [], <<"Hello World!">>, Req),
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
89 {ok, Req2, State}.
c6ad027 Introduce Handler:terminate to cleanup the handler's state.
Loïc Hoguin authored
90
2c21f0c @nox Use syntax highlighted code block in README.md
nox authored
91 terminate(Req, State) ->
92 ok.
93 ```
9b620bb Add HTTP handler loops to the README
Loïc Hoguin authored
94
95 You can also write handlers that do not reply directly. Instead, such handlers
96 will wait for an Erlang message from another process and only reply when
97 receiving such message, or timeout if it didn't arrive in time.
98
99 This is especially useful for long-polling functionality, as Cowboy will handle
100 process hibernation and timeouts properly, preventing mistakes if you were to
e4124de @essen Switch to Ranch for connection handling
essen authored
101 write the code yourself. A handler of that kind can be defined like this:
9b620bb Add HTTP handler loops to the README
Loïc Hoguin authored
102
103 ``` erlang
104 -module(my_loop_handler).
105 -export([init/3, info/3, terminate/2]).
106
107 -define(TIMEOUT, 60000).
108
109 init({tcp, http}, Req, Opts) ->
110 {loop, Req, undefined_state, ?TIMEOUT, hibernate}.
111
112 info({reply, Body}, Req, State) ->
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
113 {ok, Req2} = cowboy_req:reply(200, [], Body, Req),
9b620bb Add HTTP handler loops to the README
Loïc Hoguin authored
114 {ok, Req2, State};
115 info(Message, Req, State) ->
116 {loop, Req, State, hibernate}.
117
118 terminate(Req, State) ->
119 ok.
120 ```
121
122 It is of course possible to combine both type of handlers together as long as
123 you return the proper tuple from init/3.
124
5a7b742 Greatly improve the README.
Loïc Hoguin authored
125 Continue reading to learn how to dispatch rules and handle requests.
126
127 Dispatch rules
128 --------------
129
130 Cowboy allows you to dispatch HTTP requests directly to a specific handler
131 based on the hostname and path information from the request. It also lets
132 you define static options for the handler directly in the rules.
133
134 To match the hostname and path, Cowboy requires a list of tokens. For
0c2e222 Update version to 0.6.0
Loïc Hoguin authored
135 example, to match the "ninenines.eu" domain name, you must specify
136 `[<<"ninenines">>, <<"eu">>]`. Or, to match the "/path/to/my/resource"
cd73784 @nox Improve README
nox authored
137 you must use `[<<"path">>, <<"to">>, <<"my">>, <<"resource">>]`. All the
5a7b742 Greatly improve the README.
Loïc Hoguin authored
138 tokens must be given as binary.
139
cd73784 @nox Improve README
nox authored
140 You can use the special token `'_'` (the atom underscore) to indicate that
5a7b742 Greatly improve the README.
Loïc Hoguin authored
141 you accept anything in that position. For example if you have both
0c2e222 Update version to 0.6.0
Loïc Hoguin authored
142 "ninenines.eu" and "ninenines.fr" domains, you can use the match spec
143 `[<<"ninenines">>, '_']` to match any top level extension.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
144
4e09d77 @nox Document the path info feature
nox authored
145 Finally, you can also match multiple leading segments of the domain name and
146 multiple trailing segments of the request path using the atom `'...'` (the atom
147 ellipsis) respectively as the first host token or the last path token. For
0c2e222 Update version to 0.6.0
Loïc Hoguin authored
148 example, host rule `['...', <<"ninenines">>, <<"eu">>]` can match both
149 "cowboy.bugs.ninenines.eu" and "ninenines.eu" and path rule
3ba578d @athoune Update README.md
athoune authored
150 `[<<"projects">>, '...']` can match both "/projects" and
4e09d77 @nox Document the path info feature
nox authored
151 "/projects/cowboy/issues/42". The host leading segments and the path trailing
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
152 segments can later be retrieved through `cowboy_req:host_info/1` and
153 `cowboy_req:path_info/1`.
4e09d77 @nox Document the path info feature
nox authored
154
5a7b742 Greatly improve the README.
Loïc Hoguin authored
155 Any other atom used as a token will bind the value to this atom when
0c2e222 Update version to 0.6.0
Loïc Hoguin authored
156 matching. To follow on our hostnames example, `[<<"ninenines">>, ext]`
cd73784 @nox Improve README
nox authored
157 would bind the values `<<"eu">>` and `<<"fr">>` to the ext atom, that you
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
158 can later retrieve in your handler by calling `cowboy_req:binding/{2,3}`.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
159
cd73784 @nox Improve README
nox authored
160 You can also accept any match spec by using the atom `'_'` directly instead of
5a7b742 Greatly improve the README.
Loïc Hoguin authored
161 a list of tokens. Our hello world example above uses this to forward all
162 requests to a single handler.
163
164 There is currently no way to match multiple tokens at once.
165
166 Requests handling
167 -----------------
168
169 Requests are passed around in the Request variable. Although they are
170 defined as a record, it is recommended to access them only through the
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
171 cowboy_req module API.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
172
173 You can retrieve the HTTP method, HTTP version, peer address and port,
174 host tokens, raw host, used port, path tokens, raw path, query string
175 values, bound values from the dispatch step, header values from the
176 request. You can also read the request body, if any, optionally parsing
177 it as a query string. Finally, the request allows you to send a response
178 to the client.
179
d3dcaf1 @essen Rename cowboy_http_req to cowboy_req
essen authored
180 See the cowboy_req module for more information.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
181
182 Websockets
183 ----------
184
185 The Websocket protocol is built upon the HTTP protocol. It first sends
186 an HTTP request for an handshake, performs it and then switches
187 to Websocket. Therefore you need to write a standard HTTP handler to
188 confirm the handshake should be completed and then the Websocket-specific
189 callbacks.
190
191 A simple handler doing nothing but sending a repetitive message using
192 Websocket would look like this:
193
194 ``` erlang
195 -module(my_ws_handler).
9b620bb Add HTTP handler loops to the README
Loïc Hoguin authored
196 -export([init/3]).
293cf33 Separate message and packet handling for websockets
Loïc Hoguin authored
197 -export([websocket_init/3, websocket_handle/3,
198 websocket_info/3, websocket_terminate/3]).
5a7b742 Greatly improve the README.
Loïc Hoguin authored
199
200 init({tcp, http}, Req, Opts) ->
0e3adf1 @essen Rename cowboy_http_websocket to cowboy_websocket
essen authored
201 {upgrade, protocol, cowboy_websocket}.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
202
203 websocket_init(TransportName, Req, _Opts) ->
204 erlang:start_timer(1000, self(), <<"Hello!">>),
205 {ok, Req, undefined_state}.
206
2374aa7 Add WebSocket drafts 7, 8, 9 and 10 implementation
Loïc Hoguin authored
207 websocket_handle({text, Msg}, Req, State) ->
208 {reply, {text, << "That's what she said! ", Msg/binary >>}, Req, State};
209 websocket_handle(_Data, Req, State) ->
210 {ok, Req, State}.
293cf33 Separate message and packet handling for websockets
Loïc Hoguin authored
211
212 websocket_info({timeout, _Ref, Msg}, Req, State) ->
5a7b742 Greatly improve the README.
Loïc Hoguin authored
213 erlang:start_timer(1000, self(), <<"How' you doin'?">>),
2374aa7 Add WebSocket drafts 7, 8, 9 and 10 implementation
Loïc Hoguin authored
214 {reply, {text, Msg}, Req, State};
293cf33 Separate message and packet handling for websockets
Loïc Hoguin authored
215 websocket_info(_Info, Req, State) ->
216 {ok, Req, State}.
5a7b742 Greatly improve the README.
Loïc Hoguin authored
217
218 websocket_terminate(_Reason, _Req, _State) ->
219 ok.
220 ```
221
222 Of course you can have an HTTP handler doing both HTTP and Websocket
223 handling, but for the sake of this example we're ignoring the HTTP
224 part entirely.
225
2374aa7 Add WebSocket drafts 7, 8, 9 and 10 implementation
Loïc Hoguin authored
226 As the Websocket protocol is still a draft the API is subject to change
227 regularly when support to the most recent drafts gets added. Features may
228 be added, changed or removed before the protocol gets finalized. Cowboy
229 tries to implement all drafts transparently and give a single interface to
230 handle them all, however.
Something went wrong with that request. Please try again.