cloudkit 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/CHANGES +2 -0
  2. data/COPYING +20 -0
  3. data/README +55 -0
  4. data/Rakefile +35 -0
  5. data/TODO +22 -0
  6. data/cloudkit.gemspec +82 -0
  7. data/doc/curl.html +329 -0
  8. data/doc/images/example-code.gif +0 -0
  9. data/doc/images/json-title.gif +0 -0
  10. data/doc/images/oauth-discovery-logo.gif +0 -0
  11. data/doc/images/openid-logo.gif +0 -0
  12. data/doc/index.html +87 -0
  13. data/doc/main.css +151 -0
  14. data/doc/rest-api.html +358 -0
  15. data/examples/1.ru +3 -0
  16. data/examples/2.ru +3 -0
  17. data/examples/3.ru +6 -0
  18. data/examples/4.ru +5 -0
  19. data/examples/5.ru +10 -0
  20. data/examples/6.ru +10 -0
  21. data/examples/TOC +17 -0
  22. data/lib/cloudkit.rb +74 -0
  23. data/lib/cloudkit/flash_session.rb +22 -0
  24. data/lib/cloudkit/oauth_filter.rb +273 -0
  25. data/lib/cloudkit/oauth_store.rb +56 -0
  26. data/lib/cloudkit/openid_filter.rb +198 -0
  27. data/lib/cloudkit/openid_store.rb +101 -0
  28. data/lib/cloudkit/rack/builder.rb +120 -0
  29. data/lib/cloudkit/rack/router.rb +20 -0
  30. data/lib/cloudkit/request.rb +159 -0
  31. data/lib/cloudkit/service.rb +135 -0
  32. data/lib/cloudkit/store.rb +459 -0
  33. data/lib/cloudkit/store/adapter.rb +9 -0
  34. data/lib/cloudkit/store/extraction_view.rb +57 -0
  35. data/lib/cloudkit/store/response.rb +51 -0
  36. data/lib/cloudkit/store/response_helpers.rb +72 -0
  37. data/lib/cloudkit/store/sql_adapter.rb +36 -0
  38. data/lib/cloudkit/templates/authorize_request_token.erb +19 -0
  39. data/lib/cloudkit/templates/oauth_descriptor.erb +43 -0
  40. data/lib/cloudkit/templates/oauth_meta.erb +8 -0
  41. data/lib/cloudkit/templates/openid_login.erb +31 -0
  42. data/lib/cloudkit/templates/request_authorization.erb +23 -0
  43. data/lib/cloudkit/templates/request_token_denied.erb +18 -0
  44. data/lib/cloudkit/user_store.rb +44 -0
  45. data/lib/cloudkit/util.rb +60 -0
  46. data/test/ext_test.rb +57 -0
  47. data/test/flash_session_test.rb +22 -0
  48. data/test/helper.rb +50 -0
  49. data/test/oauth_filter_test.rb +331 -0
  50. data/test/oauth_store_test.rb +12 -0
  51. data/test/openid_filter_test.rb +54 -0
  52. data/test/openid_store_test.rb +12 -0
  53. data/test/rack_builder_test.rb +41 -0
  54. data/test/request_test.rb +197 -0
  55. data/test/service_test.rb +718 -0
  56. data/test/store_test.rb +99 -0
  57. data/test/user_store_test.rb +12 -0
  58. data/test/util_test.rb +13 -0
  59. metadata +190 -0
Binary file
Binary file
Binary file
Binary file
data/doc/index.html ADDED
@@ -0,0 +1,87 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <title>CloudKit - An Open Web JSON Appliance</title>
7
+ <link rel="stylesheet" href="main.css" type="text/css" charset="utf-8"/>
8
+ </head>
9
+ <body>
10
+ <div class="wrapper">
11
+ <ul class="nav">
12
+ <li><a href="rest-api.html" title="REST API">REST API</a></li>
13
+ <li><a href="curl.html" title="cURL Tutorial">cURL</a></li>
14
+ <li><a href="api" title="RDoc">RDoc</a></li>
15
+ <li><a href="http://github.com/jcrosby/cloudkit" title="GitHub Source Repository">Code</a></li>
16
+ <li><a href="http://blog.joncrosby.me" title="Author's Blog">Blog</a></li>
17
+ </ul>
18
+ </div>
19
+ <div id="header">
20
+ <div class="wrapper">
21
+ <h1>CloudKit</h1>
22
+ <div class="subtitle">An Open Web JSON Appliance</div>
23
+ </div>
24
+ </div>
25
+ <div class="wrapper intro-row">
26
+ <div class="column-one">
27
+ <div class="block-header">
28
+ Build APIs Like This
29
+ </div>
30
+ <img alt="Example Code" src="images/example-code.gif"/>
31
+ </div>
32
+ <div class="column-two">
33
+ <p>
34
+ CloudKit provides RESTful JSON storage with optional OpenID and OAuth
35
+ support, including OAuth Discovery. Stored entities are versioned.
36
+ Services manage their own storage and do not require schema updates
37
+ when models change.
38
+ </p>
39
+ <p>
40
+ CloudKit is Rack middleware and as such can be used on its own or
41
+ alongside other Rack-based applications or middleware components such
42
+ as Rails, Merb or Sinatra.
43
+ </p>
44
+ </div>
45
+ </div>
46
+
47
+ <div id="splitter"></div>
48
+
49
+ <div class="wrapper stack-logo-row">
50
+ <div class="column-one">
51
+ <img alt="OAuth Discovery Logo" src="images/oauth-discovery-logo.gif"/>
52
+ </div>
53
+ <div class="column-two">
54
+ <img alt="OpenID Logo" src="images/openid-logo.gif"/>
55
+ </div>
56
+ <div class="column-three">
57
+ <img alt="JSON Title" src="images/json-title.gif"/>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="wrapper stack-row">
62
+ <div class="column-one">
63
+ <p>
64
+ The CloudKit stack provides an optional OAuth Filter with support for
65
+ OAuth Core 1.0 and OAuth Discovery. Share your APIs with other
66
+ web services, desktop apps, Open Social gadgets and more.
67
+ </p>
68
+ </div>
69
+ <div class="plus">+</div>
70
+ <div class="column-two">
71
+ <p>
72
+ An OpenID Filter supplies authentication for browser-based clients.
73
+ Both the OAuth and OpenID Filters collaborate to simultaneously provide
74
+ login screens and auth challenges in a single HTTP response.
75
+ </p>
76
+ </div>
77
+ <div class="plus">+</div>
78
+ <div class="column-three">
79
+ <p>
80
+ Discoverable, schema-free, auto-versioned JSON storage tracks each
81
+ version of each JSON document to allow progressive diff/merge with
82
+ decentralized or occasionally connected clients.
83
+ </p>
84
+ </div>
85
+ </div>
86
+ </body>
87
+ </html>
data/doc/main.css ADDED
@@ -0,0 +1,151 @@
1
+ body {
2
+ font-family: 'Helvetica', 'Arial', san-serif;
3
+ font-size: 15px;
4
+ margin: 0;
5
+ padding: 0;
6
+ color: #222222;
7
+ }
8
+ h1 {
9
+ font-family: 'Helvetica Neue', 'Helvetica', 'Arial', san-serif;
10
+ font-size: 73px;
11
+ font-weight: bold;
12
+ line-height: 28px;
13
+ margin: 20px 0px 20px 0px;
14
+ }
15
+ .wrapper {
16
+ width: 860px;
17
+ margin: 0 auto;
18
+ clear: both;
19
+ }
20
+ .intro-row {
21
+ margin-top: 28px;
22
+ }
23
+ .stack-logo-row {
24
+ margin-bottom: 150px;
25
+ }
26
+ .stack-row {
27
+ margin-top: 28px;
28
+ }
29
+ .column-one {
30
+ width: 240px;
31
+ float: left;
32
+ }
33
+ .column-two {
34
+ margin-left: 70px;
35
+ float: left;
36
+ width: 240px;
37
+ }
38
+ .column-two img {
39
+ padding-top: 15px;
40
+ }
41
+ p {
42
+ margin-top: 0px;
43
+ line-height: 1.5em;
44
+ }
45
+ .column-three {
46
+ float: right;
47
+ width: 240px;
48
+ margin-left: 70px;
49
+ }
50
+ .stack-row .column-two {
51
+ margin-left: 0px;
52
+ }
53
+ .column-three img {
54
+ padding-top: 35px;
55
+ }
56
+ .stack-row .column-three {
57
+ margin-left: 0px;
58
+ }
59
+ .plus {
60
+ color: #ffcc66;
61
+ float: left;
62
+ width: 70px;
63
+ font-size: 35px;
64
+ margin-top: 35px;
65
+ text-align: center;
66
+ }
67
+ #splitter {
68
+ border-top: 1px solid #ffcc66;
69
+ clear: both;
70
+ margin-bottom: 28px;
71
+ }
72
+ #header {
73
+ background-color: #ffffcc;
74
+ display: block;
75
+ padding: 2px 0;
76
+ margin: 35px 0px 10px 0px;
77
+ border-top: 1px solid #ffcc66;
78
+ border-bottom: 1px solid #ffcc66;
79
+ }
80
+ #header .wrapper .subtitle {
81
+ margin-left: 110px;
82
+ font-family: 'Helvetica Neue', 'Helvetica', 'Arial', san-serif;
83
+ font-size: 30px;
84
+ }
85
+ #header .wrapper .subpage-subtitle {
86
+ margin-left: 10px;
87
+ font-family: 'Helvetica Neue', 'Helvetica', 'Arial', san-serif;
88
+ font-size: 30px;
89
+ }
90
+ #header a {
91
+ color: #222222;
92
+ }
93
+ ul.nav {
94
+ list-style: none;
95
+ float: right;
96
+ font-size: 17px;
97
+ margin: -28px 0;
98
+ height: 20px;
99
+ }
100
+ ul.nav li {
101
+ float: left;
102
+ margin-left: 28px;
103
+ }
104
+ ul.nav li a {
105
+ color: #222222;
106
+ }
107
+ a {
108
+ color: #6b8df2;
109
+ text-decoration: none;
110
+ }
111
+ .block-header {
112
+ font-size: 20px;
113
+ font-weight: bold;
114
+ margin-bottom: 7px;
115
+ }
116
+ .code {
117
+ padding: 7px;
118
+ font-family: 'Courier New', monospace;
119
+ color: #00ff00;
120
+ background-color: black;
121
+ font-size: 13px;
122
+ width: 100%;
123
+ margin-left: 20px;
124
+ margin-bottom: 30px;
125
+ }
126
+ .meta {
127
+ padding: 7px 7px 7px 7px;
128
+ background-color: #ffccff;
129
+ border-top: 1px solid #cc99ff;
130
+ border-bottom: 1px solid #cc99ff;
131
+ font-size: 14px;
132
+ display: block;
133
+ margin: 10px 0px 10px 0px;
134
+ }
135
+ .uri-template {
136
+ font-family: 'Courier New', monospace;
137
+ color: #00ff00;
138
+ background-color: black;
139
+ width: 860px;
140
+ padding-left: 5px;
141
+ padding-top: 10px;
142
+ padding-bottom: 10px;
143
+ margin-top: 30px;
144
+ }
145
+ .spec-header {
146
+ font-weight: bold;
147
+ font-size: 15px;
148
+ }
149
+ .definition {
150
+ font-weight: bold;
151
+ }
data/doc/rest-api.html ADDED
@@ -0,0 +1,358 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+ <title>CloudKit REST API</title>
7
+ <link rel="stylesheet" href="main.css" type="text/css" charset="utf-8"/>
8
+ </head>
9
+ <body>
10
+ <div class="wrapper">
11
+ <ul class="nav">
12
+ <li><a href="rest-api.html" title="REST API">REST API</a></li>
13
+ <li><a href="curl.html" title="cURL Tutorial">cURL</a></li>
14
+ <li><a href="api" title="RDoc">RDoc</a></li>
15
+ <li><a href="http://github.com/jcrosby/cloudkit" title="GitHub Source Repository">Code</a></li>
16
+ <li><a href="http://blog.joncrosby.me" title="Author's Blog">Blog</a></li>
17
+ </ul>
18
+ </div>
19
+ <div id="header">
20
+ <div class="wrapper">
21
+ <h1><a href="index.html">CloudKit</a></h1>
22
+ <div class="subpage-subtitle">REST API</div>
23
+ </div>
24
+ </div>
25
+ <div class="meta">
26
+ <div class="wrapper">
27
+ <p>All request and response bodies are JSON documents.</p>
28
+
29
+ <p>URI and JSON templates in this document are represented as follows:<br/>
30
+ - Values in %% are variables.<br/>
31
+ - All other symbols are literals.<br/>
32
+ </p>
33
+
34
+ <p>All URIs are relative to the service root, which can be mounted in any
35
+ number of ways using Rack's URL Maps and Cascades. See the examples
36
+ directory in the source for specific techniques.
37
+ </p>
38
+
39
+ <p>All response codes closely follow RFC 2616 with the addition of 422 from
40
+ RFC 4918.
41
+ </p>
42
+
43
+ <p>All errors use JSON to supplement their status codes:<br/>
44
+ {"error":"%message%"}
45
+ </p>
46
+ </div>
47
+ </div>
48
+ <div class="wrapper">
49
+
50
+ <div class="uri-template">
51
+ GET /cloudkit-meta
52
+ </div>
53
+ <p>
54
+ List resource collection URIs hosted at the service root.
55
+ </p>
56
+
57
+ <p>
58
+ <span class="spec-header">Response:</span><br/>
59
+ {"uris":[%collection-uri-list%]}
60
+ </p>
61
+
62
+ <p>
63
+ <span class="spec-header">Response Variables:</span><br/>
64
+ <span class="definition">collection-uri-list:</span> an array of collection URIs hosted at the service root.
65
+ </p>
66
+
67
+ <div class="uri-template">
68
+ OPTIONS /%uri%
69
+ </div>
70
+ <p>
71
+ Return an Allow header containing the available methods for a given URI.
72
+ </p>
73
+
74
+ <div class="uri-template">
75
+ GET /%collection%
76
+ </div>
77
+ <p>
78
+ List URIs of available documents within a collection. This includes only
79
+ current version URIs. Previous versions of a given document are hosted under a
80
+ different URI. Sort order is descending by last modified date.
81
+ </p>
82
+
83
+ <p>
84
+ <span class="spec-header">URI Variables:</span><br/>
85
+ <span class="definition">collection:</span> a named collection of JSON documents.
86
+ </p>
87
+
88
+ <p>
89
+ <span class="spec-header">Optional Query Parameters:</span><br/>
90
+ <span class="definition">offset:</span> 0-based starting index for the list of results. Default is 0.<br/>
91
+ <span class="definition">limit:</span> maximum number of results to return. Default is undefined, meaning unlimited.
92
+ </p>
93
+
94
+ <p>
95
+ <span class="spec-header">Response:</span><br/>
96
+ {<br/>
97
+ "total":%total-results%,<br/>
98
+ "offset":%offset-value%,<br/>
99
+ "uris":[%uri-list%]<br/>
100
+ }
101
+ </p>
102
+
103
+ <p>
104
+ <span class="spec-header">Response Variables:</span><br/>
105
+ <span class="definition">total-results:</span> the total number of available results in the complete set, calculated prior applying any provided limits.<br/>
106
+ <span class="definition">offset-value:</span> integer representing the offset.<br/>
107
+ <span class="definition">uri-list:</span> an array of document URIs within the given collection. If less than the total available are supplied in the uris element, additional requests can be made, specifying the offset and limit query parameters. Future versions of CloudKit may page result sets to optimize performance.
108
+ </p>
109
+
110
+
111
+ <div class="uri-template">
112
+ GET /%collection%/%uuid%
113
+ </div>
114
+ <p>
115
+ Return the current version of a JSON document.
116
+ </p>
117
+
118
+ <p>
119
+ <span class="spec-header">URI Variables:</span><br/>
120
+ <span class="definition">collection:</span> a named collection of documents.<br/>
121
+ <span class="definition">uuid:</span> the unique key for a JSON document.
122
+ </p>
123
+
124
+ <p>
125
+ <span class="spec-header">Response:</span><br/>
126
+ %json-document%
127
+ </p>
128
+
129
+ <p>
130
+ <span class="spec-header">Response Variables:</span><br/>
131
+ <span class="definition">json-document:</span> a valid JSON document.
132
+ </p>
133
+
134
+ <div class="uri-template">
135
+ GET /%collection%/%uuid%/versions
136
+ </div>
137
+ <p>
138
+ List URIs of all versions of a given JSON document. This is a union of current
139
+ and previous document versions. Sort order is descending by last modified date.
140
+ </p>
141
+
142
+ <p>
143
+ <span class="spec-header">URI Variables:</span><br/>
144
+ <span class="definition">collection:</span> a named collection of JSON documents.<br/>
145
+ <span class="definition">uuid:</span> the unique key for a JSON document.
146
+ </p>
147
+
148
+ <p>
149
+ <span class="spec-header">Optional Query Parameters:</span><br/>
150
+ <span class="definition">offset:</span> 0-based starting index for the list of results. Default is 0.<br/>
151
+ <span class="definition">limit:</span> maximum number of results to return. Default is undefined, meaning unlimited.
152
+ </p>
153
+
154
+ <p>
155
+ <span class="spec-header">Response:</span><br/>
156
+ {<br/>
157
+ "total":%total-results%,<br/>
158
+ "offset":%offset-value%,<br/>
159
+ "uris":[%uri-list%]<br/>
160
+ }
161
+ </p>
162
+
163
+ <p>
164
+ <span class="spec-header">Response Variables:</span><br/>
165
+ <span class="definition">total-results:</span> the total number of available results in the complete set, calculated prior to applying any provided limits.<br/>
166
+ <span class="definition">offset-value:</span> integer representing the offset.<br/>
167
+ <span class="definition">uri-list:</span> an array of document URIs within the given collection. If less than the total available are supplied in the uris element, additional requests can be made, specifying the offset and limit query parameters. Future versions of CloudKit may page result sets to optimize performance.
168
+ </p>
169
+
170
+ <div class="uri-template">
171
+ GET /%collection%/%uuid%/versions/%etag%
172
+ </div>
173
+ <p>
174
+ Return the given version of a JSON document as specified by its ETag.
175
+ </p>
176
+
177
+ <p>
178
+ <span class="spec-header">URI Variables:</span><br/>
179
+ <span class="definition">collection:</span> a named collection of documents.<br/>
180
+ <span class="definition">uuid:</span> the unique key for a JSON document.<br/>
181
+ <span class="definition">etag:</span> the ETag of the desired document version.
182
+ </p>
183
+
184
+ <p>
185
+ <span class="spec-header">Response:</span><br/>
186
+ %json-document%
187
+ </p>
188
+
189
+ <p>
190
+ <span class="spec-header">Response Variables:</span><br/>
191
+ <span class="definition">json-document:</span> a valid JSON document.
192
+ </p>
193
+
194
+ <div class="uri-template">
195
+ POST /%collection%
196
+ </div>
197
+ <p>
198
+ Create a resource within the given collection using the provided JSON document.
199
+ </p>
200
+
201
+ <p>
202
+ <span class="spec-header">URI Variables:</span><br/>
203
+ <span class="definition">collection:</span> a named collection of documents.
204
+ </p>
205
+
206
+ <p>
207
+ <span class="spec-header">Request Body:</span><br/>
208
+ %json-document%
209
+ </p>
210
+
211
+ <p>
212
+ <span class="spec-header">Request Body Variables:</span><br/>
213
+ <span class="definition">json-document:</span> a valid JSON document.
214
+ </p>
215
+
216
+ <p>
217
+ <span class="spec-header">Response:</span><br/>
218
+ {<br/>
219
+ "ok":true,<br/>
220
+ "uri":%uri%,<br/>
221
+ "etag":%etag%,<br/>
222
+ "last_modified":%last-modified%<br/>
223
+ }
224
+ </p>
225
+
226
+ <p>
227
+ <span class="spec-header">Response Variables:</span><br/>
228
+ <span class="definition">uri:</span> the URI for the stored document relative to the service root.<br/>
229
+ <span class="definition">etag:</span> the ETag for the current version of the submitted document.<br/>
230
+ <span class="definition">last_modified:</span> the Last-Modified timestamp for the submitted document according to the service. This is different from any client last_modified timestamps that may be embedded as a regular part of the JSON document body.
231
+ </p>
232
+
233
+ <p>
234
+ <span class="spec-header">Error Response:</span><br/>
235
+ {<br/>
236
+ "error":%message%<br/>
237
+ }
238
+ </p>
239
+
240
+ <p>
241
+ <span class="spec-header">Error Response Variables:</span><br/>
242
+ <span class="definition">message:</span> a short description of the source of the error.
243
+ </p>
244
+
245
+
246
+ <div class="uri-template">
247
+ PUT /%collection%/%uuid%
248
+ </div>
249
+ <p>
250
+ Create or update the resource at the given URI.
251
+ </p>
252
+
253
+ <p>
254
+ <span class="spec-header">URI Variables:</span><br/>
255
+ <span class="definition">collection:</span> a named collection of documents.<br/>
256
+ <span class="definition">uuid:</span> the unique key for a JSON document that is being created or updated.
257
+ </p>
258
+
259
+ <p>
260
+ <span class="spec-header">Request Body:</span><br/>
261
+ %json-document%
262
+ </p>
263
+
264
+ <p>
265
+ <span class="spec-header">Request Body Variables:</span><br/>
266
+ <span class="definition">json-document:</span> a valid JSON document.
267
+ </p>
268
+
269
+ <p>
270
+ <span class="spec-header">Request Headers:</span><br/>
271
+ <span class="definition">If-Match:</span> required for documents that are being updated. Ignored for new document storage.
272
+ </p>
273
+
274
+ <p>
275
+ <span class="spec-header">Response:</span><br/>
276
+ {<br/>
277
+ "ok":true,<br/>
278
+ "uri":%uri%,<br/>
279
+ "etag":%etag%,<br/>
280
+ "last_modified":%last-modified%<br/>
281
+ }
282
+ </p>
283
+
284
+ <p>
285
+ <span class="spec-header">Response Variables:</span><br/>
286
+ <span class="definition">uri:</span> the URI for the stored document relative to the service root.<br/>
287
+ <span class="definition">etag:</span> the ETag for the current version of the submitted document.<br/>
288
+ <span class="definition">last_modified:</span> the Last-Modified timestamp for the submitted document according to the service. This is different from any client last_modified timestamps that may be embedded as a regular part of the JSON document body.
289
+ </p>
290
+
291
+ <p>
292
+ <span class="spec-header">Error Response:</span><br/>
293
+ {<br/>
294
+ "error":%message%<br/>
295
+ }
296
+ </p>
297
+
298
+ <p>
299
+ <span class="spec-header">Error Response Variables:</span><br/>
300
+ <span class="definition">message:</span> a short description of the source of the error.
301
+ </p>
302
+
303
+ <div class="uri-template">
304
+ DELETE /%collection%/%uuid%
305
+ </div>
306
+ <p>
307
+ Delete the document at the given URI.
308
+ </p>
309
+
310
+ <p>
311
+ <span class="spec-header">URI Variables:</span><br/>
312
+ <span class="definition">collection:</span> a named collection of documents.<br/>
313
+ <span class="definition">uuid:</span> the unique key for a JSON document that is being created or updated.
314
+ </p>
315
+
316
+ <p>
317
+ <span class="spec-header">Request Headers:</span><br/>
318
+ <span class="definition">If-Match:</span> required for documents that are being updated. Ignored for new document storage.
319
+ </p>
320
+
321
+ <p>
322
+ <span class="spec-header">Response:</span><br/>
323
+ {<br/>
324
+ "ok":true,<br/>
325
+ "uri":%uri%,<br/>
326
+ "etag":%etag%,<br/>
327
+ "last_modified":%last-modified%<br/>
328
+ }
329
+ </p>
330
+
331
+ <p>
332
+ <span class="spec-header">Response Variables:</span><br/>
333
+ <span class="definition">uri:</span> the URI for the stored document relative to the service root. In the case of DELETE, this is the URI for archived resource version.<br/>
334
+ <span class="definition">etag:</span> the ETag for the current version of the document, now archived. This ETag will match the previous version as new ETags are not relevant to deleted resources.<br/>
335
+ <span class="definition">last_modified:</span> the Last-Modified timestamp for the document according to the service. This is different from any client last_modified timestamps that may be embedded as a regular part of the JSON document body. Note that this last_modified timestamp matches the previous version.
336
+ </p>
337
+
338
+ <p>
339
+ <span class="spec-header">Error Response:</span><br/>
340
+ {<br/>
341
+ "error":%message%<br/>
342
+ }
343
+ </p>
344
+
345
+ <p>
346
+ <span class="spec-header">Error Response Variables:</span><br/>
347
+ <span class="definition">message:</span> a short description of the source of the error.
348
+ </p>
349
+
350
+ <div class="uri-template">
351
+ HEAD /%uri%
352
+ </div>
353
+ <p>
354
+ Return the headers for an identical GET at the same URI.
355
+ </p>
356
+ </div>
357
+ </body>
358
+ </html>