summaryrefslogtreecommitdiffstats
path: root/docs/en/cowboy/2.4/guide/resource_design/index.html
blob: e966aa4caec14776912b5c0074d5c40eded1c722 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <meta name="author" content="Loïc Hoguin based on a design from (Soft10) Pol Cámara">

    <meta name="generator" content="Hugo 0.37.1" />

    <title>Nine Nines: Designing a resource handler</title>

    <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic' rel='stylesheet' type='text/css'>
    <link href="/css/99s.css?r=1" rel="stylesheet">

    <link rel="shortcut icon" href="/img/ico/favicon.ico">
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/img/ico/apple-touch-icon-114.png">
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="/img/ico/apple-touch-icon-72.png">
    <link rel="apple-touch-icon-precomposed" href="/img/ico/apple-touch-icon-57.png">

    
</head>


<body class="">
  <header id="page-head">
    <div id="topbar" class="container">
        <div class="row">
          <div class="span2">
            <h1 id="logo"><a href="/" title="99s">99s</a></h1>
          </div>
          <div class="span10">
            
            <div id="side-header">
              <nav>
                <ul>
                  <li><a title="Hear my thoughts" href="/articles">Articles</a></li>
  				  <li><a title="Watch my talks" href="/talks">Talks</a></li>
  				  <li class="active"><a title="Read the docs" href="/docs">Documentation</a></li>
  				  <li><a title="Request my services" href="/services">Consulting & Training</a></li>
                </ul>
              </nav> 
              <ul id="social">
                <li>
                  <a href="https://github.com/ninenines" title="Check my Github repositories"><img src="/img/ico_github.png" data-hover="/img/ico_github_alt.png" alt="Github"></a>
                </li>
                    <li>
						<a title="Contact me" href="mailto:[email protected]"><img src="/img/ico_mail.png" data-hover="/img/ico_mail_alt.png"></a>
					</li>
              </ul>
            </div>
          </div>
        </div>
    </div>


</header>

<div id="contents" class="two_col">
<div class="container">
<div class="row">
<div id="docs" class="span9 maincol">

<h1 class="lined-header"><span>Designing a resource handler</span></h1>

<div class="paragraph"><p>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.</p></div>
<div class="sect1">
<h2 id="_the_service">The service</h2>
<div class="sectionbody">
<div class="paragraph"><p>Can the service become unavailable, and when it does, can
we detect it? For example, database connectivity problems
may be detected early. We may also have planned outages
of all or parts of the system. Implement the
<code>service_available</code> callback.</p></div>
<div class="paragraph"><p>What HTTP methods does the service implement? Do we need
more than the standard OPTIONS, HEAD, GET, PUT, POST,
PATCH and DELETE? Are we not using one of those at all?
Implement the <code>known_methods</code> callback.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_type_of_resource_handler">Type of resource handler</h2>
<div class="sectionbody">
<div class="paragraph"><p>Am I writing a handler for a collection of resources,
or for a single resource?</p></div>
<div class="paragraph"><p>The semantics for each of these are quite different.
You should not mix collection and single resource in
the same handler.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_collection_handler">Collection handler</h2>
<div class="sectionbody">
<div class="paragraph"><p>Skip this section if you are not doing a collection.</p></div>
<div class="paragraph"><p>Is the collection hardcoded or dynamic? For example,
if you use the route <code>/users</code> for the collection of
users then the collection is hardcoded; if you use
<code>/forums/:category</code> for the collection of threads
then it isn&#8217;t. When the collection is hardcoded you
can safely assume the resource always exists.</p></div>
<div class="paragraph"><p>What methods should I implement?</p></div>
<div class="paragraph"><p>OPTIONS is used to get some information about the
collection. It is recommended to allow it even if you
do not implement it, as Cowboy has a default
implementation built-in.</p></div>
<div class="paragraph"><p>HEAD and GET are used to retrieve the collection.
If you allow GET, also allow HEAD as there&#8217;s no extra
work required to make it work.</p></div>
<div class="paragraph"><p>POST is used to create a new resource inside the
collection. Creating a resource by using POST on
the collection is useful when resources may be
created before knowing their URI, usually because
parts of it are generated dynamically. A common
case is some kind of auto incremented integer
identifier.</p></div>
<div class="paragraph"><p>The next methods are more rarely allowed.</p></div>
<div class="paragraph"><p>PUT is used to create a new collection (when
the collection isn&#8217;t hardcoded), or replace
the entire collection.</p></div>
<div class="paragraph"><p>DELETE is used to delete the entire collection.</p></div>
<div class="paragraph"><p>PATCH is used to modify the collection using
instructions given in the request body. A PATCH
operation is atomic. The PATCH operation may
be used for such things as reordering; adding,
modifying or deleting parts of the collection.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_single_resource_handler">Single resource handler</h2>
<div class="sectionbody">
<div class="paragraph"><p>Skip this section if you are doing a collection.</p></div>
<div class="paragraph"><p>What methods should I implement?</p></div>
<div class="paragraph"><p>OPTIONS is used to get some information about the
resource. It is recommended to allow it even if you
do not implement it, as Cowboy has a default
implementation built-in.</p></div>
<div class="paragraph"><p>HEAD and GET are used to retrieve the resource.
If you allow GET, also allow HEAD as there&#8217;s no extra
work required to make it work.</p></div>
<div class="paragraph"><p>POST is used to update the resource.</p></div>
<div class="paragraph"><p>PUT is used to create a new resource (when it doesn&#8217;t
already exist) or replace the resource.</p></div>
<div class="paragraph"><p>DELETE is used to delete the resource.</p></div>
<div class="paragraph"><p>PATCH is used to modify the resource using
instructions given in the request body. A PATCH
operation is atomic. The PATCH operation may
be used for adding, removing or modifying specific
values in the resource.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_resource">The resource</h2>
<div class="sectionbody">
<div class="paragraph"><p>Following the above discussion, implement the
<code>allowed_methods</code> callback.</p></div>
<div class="paragraph"><p>Does the resource always exist? If it may not, implement
the <code>resource_exists</code> callback.</p></div>
<div class="paragraph"><p>Do I need to authenticate the client before they can
access the resource? What authentication mechanisms
should I provide? This may include form-based, token-based
(in the URL or a cookie), HTTP basic, HTTP digest,
SSL certificate or any other form of authentication.
Implement the <code>is_authorized</code> callback.</p></div>
<div class="paragraph"><p>Do I need fine-grained access control? How do I determine
that they are authorized access? Handle that in your
<code>is_authorized</code> callback.</p></div>
<div class="paragraph"><p>Can access to a resource be forbidden regardless of access
being authorized? A simple example of that is censorship
of a resource. Implement the <code>forbidden</code> callback.</p></div>
<div class="paragraph"><p>Are 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 <code>uri_too_long</code>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_representations">Representations</h2>
<div class="sectionbody">
<div class="paragraph"><p>What media types do I provide? If text based, what charsets
are provided? What languages do I provide?</p></div>
<div class="paragraph"><p>Implement the mandatory <code>content_types_provided</code>. Prefix
the callbacks with <code>to_</code> for clarity. For example, <code>to_html</code>
or <code>to_text</code>.</p></div>
<div class="paragraph"><p>Implement the <code>languages_provided</code> or <code>charsets_provided</code>
callbacks if applicable.</p></div>
<div class="paragraph"><p>Is there any other header that may make the representation
of the resource vary? Implement the <code>variances</code> callback.</p></div>
<div class="paragraph"><p>Depending on your choices for caching content, you may
want to implement one or more of the <code>generate_etag</code>,
<code>last_modified</code> and <code>expires</code> callbacks.</p></div>
<div class="paragraph"><p>Do I want the user or user agent to actively choose a
representation available? Send a list of available
representations in the response body and implement
the <code>multiple_choices</code> callback.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_redirections">Redirections</h2>
<div class="sectionbody">
<div class="paragraph"><p>Do I need to keep track of what resources were deleted?
For example, you may have a mechanism where moving a
resource leaves a redirect link to its new location.
Implement the <code>previously_existed</code> callback.</p></div>
<div class="paragraph"><p>Was the resource moved, and is the move temporary? If
it is explicitly temporary, for example due to maintenance,
implement the <code>moved_temporarily</code> callback. Otherwise,
implement the <code>moved_permanently</code> callback.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_request">The request</h2>
<div class="sectionbody">
<div class="paragraph"><p>Do you need to read the query string? Individual headers?
Implement <code>malformed_request</code> and do all the parsing and
validation in this function. Note that the body should not
be read at this point.</p></div>
<div class="paragraph"><p>May there be a request body? Will I know its size?
What&#8217;s the maximum size of the request body I&#8217;m willing
to accept? Implement <code>valid_entity_length</code>.</p></div>
<div class="paragraph"><p>Finally, take a look at the sections corresponding to the
methods you are implementing.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_options_method">OPTIONS method</h2>
<div class="sectionbody">
<div class="paragraph"><p>Cowboy by default will send back a list of allowed methods.
Do I need to add more information to the response? Implement
the <code>options</code> method.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_get_and_head_methods">GET and HEAD methods</h2>
<div class="sectionbody">
<div class="paragraph"><p>If you implement the methods GET and/or HEAD, you must
implement one <code>ProvideResource</code> callback for each
content-type returned by the <code>content_types_provided</code>
callback.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_put_post_and_patch_methods">PUT, POST and PATCH methods</h2>
<div class="sectionbody">
<div class="paragraph"><p>If you implement the methods PUT, POST and/or PATCH,
you must implement the <code>content_types_accepted</code> callback,
and one <code>AcceptCallback</code> callback for each content-type
it returns. Prefix the <code>AcceptCallback</code> callback names
with <code>from_</code> for clarity. For example, <code>from_html</code> or
<code>from_json</code>.</p></div>
<div class="paragraph"><p>Do we want to allow the POST method to create individual
resources directly through their URI (like PUT)? Implement
the <code>allow_missing_post</code> callback. It is recommended to
explicitly use PUT in these cases instead.</p></div>
<div class="paragraph"><p>May there be conflicts when using PUT to create or replace
a resource? Do we want to make sure that two updates around
the same time are not cancelling one another? Implement the
<code>is_conflict</code> callback.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_delete_methods">DELETE methods</h2>
<div class="sectionbody">
<div class="paragraph"><p>If you implement the method DELETE, you must implement
the <code>delete_resource</code> callback.</p></div>
<div class="paragraph"><p>When <code>delete_resource</code> returns, is the resource completely
removed from the server, including from any caching service?
If not, and/or if the deletion is asynchronous and we have
no way of knowing it has been completed yet, implement the
<code>delete_completed</code> callback.</p></div>
</div>
</div>



	
		
		
		
		
		

		<nav style="margin:1em 0">
			
				<a style="float:left" href="https://ninenines.eu/docs/en/cowboy/2.4/guide/rest_flowcharts/">
					REST flowcharts
				</a>
			

			
				<a style="float:right" href="https://ninenines.eu/docs/en/cowboy/2.4/guide/ws_protocol/">
					The Websocket protocol
				</a>
			
		</nav>
	



</div>

<div class="span3 sidecol">


<h3>
	Cowboy
	2.4
	
	User Guide
</h3>

<ul>
	
		<li><a href="/docs/en/cowboy/2.4/guide">User Guide</a></li>
	
	
		<li><a href="/docs/en/cowboy/2.4/manual">Function Reference</a></li>
	
	
</ul>

<h4 id="docs-nav">Navigation</h4>

<h4>Version select</h4>
<ul>
	
	
	
		<li><a href="/docs/en/cowboy/2.4/guide">2.4</a></li>
	
		<li><a href="/docs/en/cowboy/2.3/guide">2.3</a></li>
	
		<li><a href="/docs/en/cowboy/2.2/guide">2.2</a></li>
	
		<li><a href="/docs/en/cowboy/2.1/guide">2.1</a></li>
	
		<li><a href="/docs/en/cowboy/2.0/guide">2.0</a></li>
	
		<li><a href="/docs/en/cowboy/1.0/guide">1.0</a></li>
	
</ul>

</div>
</div>
</div>
</div>

      <footer>
        <div class="container">
          <div class="row">
            <div class="span6">
              <p id="scroll-top"><a href="#">↑ Scroll to top</a></p>
              <nav>
                <ul>
                  <li><a href="mailto:[email protected]" title="Contact us">Contact us</a></li><li><a href="https://github.com/ninenines/ninenines.github.io" title="Github repository">Contribute to this site</a></li>
                </ul>
              </nav>
            </div>
            <div class="span6 credits">
               <p><img src="/img/footer_logo.png"></p>
               <p>Copyright &copy; Loïc Hoguin 2012-2018</p>
            </div>
          </div>
        </div>
      </footer>

    
    <script src="/js/custom.js"></script>
  </body>
</html>