cloudkit 0.9.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/COPYING +1 -1
- data/README +7 -7
- data/TODO +4 -3
- data/cloudkit.gemspec +4 -4
- data/doc/curl.html +133 -72
- data/doc/index.html +1 -1
- data/doc/rest-api.html +109 -0
- data/examples/3.ru +1 -1
- data/examples/4.ru +1 -1
- data/examples/5.ru +2 -2
- data/examples/6.ru +2 -2
- data/lib/cloudkit.rb +7 -1
- data/lib/cloudkit/constants.rb +40 -0
- data/lib/cloudkit/oauth_filter.rb +9 -9
- data/lib/cloudkit/oauth_store.rb +1 -5
- data/lib/cloudkit/openid_filter.rb +11 -11
- data/lib/cloudkit/rack/builder.rb +3 -3
- data/lib/cloudkit/request.rb +18 -12
- data/lib/cloudkit/service.rb +26 -8
- data/lib/cloudkit/store.rb +109 -34
- data/lib/cloudkit/store/adapter.rb +0 -1
- data/lib/cloudkit/store/response.rb +1 -0
- data/lib/cloudkit/store/sql_adapter.rb +2 -2
- data/lib/cloudkit/util.rb +2 -37
- data/test/helper.rb +6 -39
- data/test/oauth_filter_test.rb +13 -13
- data/test/openid_filter_test.rb +14 -8
- data/test/request_test.rb +6 -6
- data/test/service_test.rb +337 -113
- data/test/store_test.rb +4 -10
- metadata +4 -4
- data/lib/cloudkit/rack/lint.rb +0 -12
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.10.0
|
2
|
+
- Updated for Rack 0.9
|
3
|
+
- Added batch URI resolution for resource collections
|
4
|
+
- Refactored use of constants
|
5
|
+
- Updated documentation
|
6
|
+
|
1
7
|
0.9.1
|
2
8
|
- Fixed Rack::Lint/rackup errors related to Content-Type headers
|
3
9
|
- Patched Rack to support StringIO#string in Rack::Lint::InputWrapper
|
data/COPYING
CHANGED
data/README
CHANGED
@@ -24,7 +24,7 @@ In a different rackup file:
|
|
24
24
|
require 'cloudkit'
|
25
25
|
contain :notes, :todos
|
26
26
|
|
27
|
-
The
|
27
|
+
The above provides the same API as example 1 with added authentication and authorization via OpenID and OAuth, respectively.
|
28
28
|
|
29
29
|
An explicit version of example 2, minus the default developer landing page:
|
30
30
|
|
@@ -33,19 +33,19 @@ An explicit version of example 2, minus the default developer landing page:
|
|
33
33
|
use CloudKit::OAuthFilter
|
34
34
|
use CloudKit::OpenIDFilter
|
35
35
|
use CloudKit::Service, :collections => [:notes, :todos]
|
36
|
-
run lambda {|env| [200, {'Content-Type' => 'text/html'}, ['HELLO']]}
|
36
|
+
run lambda {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']]}
|
37
37
|
|
38
38
|
The same as above, using MySQL:
|
39
39
|
|
40
40
|
require 'cloudkit'
|
41
|
-
use Rack::Config
|
42
|
-
env[
|
43
|
-
|
41
|
+
use Rack::Config do |env|
|
42
|
+
env[CLOUDKIT_STORAGE_URI] = 'mysql://user:pass@localhost/cloudkit_example'
|
43
|
+
end
|
44
44
|
use Rack::Pool::Session
|
45
45
|
use CloudKit::OAuthFilter
|
46
46
|
use CloudKit::OpenIDFilter
|
47
47
|
use CloudKit::Service, :collections => [:notes, :todos]
|
48
|
-
run lambda {|env| [200, {'Content-Type' => 'text/html'}, ['HELLO']]}
|
48
|
+
run lambda {|env| [200, {'Content-Type' => 'text/html', 'Content-Length' => '5'}, ['HELLO']]}
|
49
49
|
|
50
50
|
See the examples directory for more.
|
51
51
|
|
@@ -61,7 +61,7 @@ Source: http://github.com/jcrosby/cloudkit
|
|
61
61
|
|
62
62
|
===License
|
63
63
|
|
64
|
-
Copyright (c) 2008 Jon Crosby http://joncrosby.me
|
64
|
+
Copyright (c) 2008, 2009 Jon Crosby http://joncrosby.me
|
65
65
|
|
66
66
|
Permission is hereby granted, free of charge, to any person obtaining
|
67
67
|
a copy of this software and associated documentation files (the
|
data/TODO
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
- jquery.cloudkit
|
3
3
|
titanium/gears
|
4
4
|
- openid sreg
|
5
|
-
- titanium middleware
|
6
|
-
version/upgrade middleware
|
7
|
-
rake automation
|
8
5
|
- oauth token management
|
9
6
|
- oauth consumer registration
|
10
7
|
- acls i.e. allowed methods per user per uri
|
@@ -14,9 +11,13 @@
|
|
14
11
|
- custom templates for openid / oauth
|
15
12
|
|
16
13
|
Backlog
|
14
|
+
- batch updates (post, put, delete)
|
17
15
|
- expect header/100-continue
|
18
16
|
- deployable gem + admin app
|
19
17
|
- cappuccino adapter
|
20
18
|
- sproutcore adapter
|
21
19
|
- tokyocabinet
|
22
20
|
- ldap adapter for UserStore
|
21
|
+
- titanium middleware
|
22
|
+
version/upgrade middleware
|
23
|
+
rake automation
|
data/cloudkit.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
s.name = "cloudkit"
|
5
|
-
s.version = "0.
|
6
|
-
s.date = "2008-
|
5
|
+
s.version = "0.10.0"
|
6
|
+
s.date = "2008-01-09"
|
7
7
|
s.summary = "An Open Web JSON Appliance."
|
8
8
|
s.description = "An Open Web JSON Appliance."
|
9
9
|
s.authors = ["Jon Crosby"]
|
@@ -32,13 +32,13 @@ Gem::Specification.new do |s|
|
|
32
32
|
examples/6.ru
|
33
33
|
examples/TOC
|
34
34
|
lib/cloudkit.rb
|
35
|
+
lib/cloudkit/constants.rb
|
35
36
|
lib/cloudkit/flash_session.rb
|
36
37
|
lib/cloudkit/oauth_filter.rb
|
37
38
|
lib/cloudkit/oauth_store.rb
|
38
39
|
lib/cloudkit/openid_filter.rb
|
39
40
|
lib/cloudkit/openid_store.rb
|
40
41
|
lib/cloudkit/rack/builder.rb
|
41
|
-
lib/cloudkit/rack/lint.rb
|
42
42
|
lib/cloudkit/rack/router.rb
|
43
43
|
lib/cloudkit/request.rb
|
44
44
|
lib/cloudkit/service.rb
|
@@ -73,7 +73,7 @@ Gem::Specification.new do |s|
|
|
73
73
|
s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
|
74
74
|
s.rubyforge_project = "cloudkit"
|
75
75
|
s.rubygems_version = "1.1.1"
|
76
|
-
s.add_dependency 'rack', '~> 0.
|
76
|
+
s.add_dependency 'rack', '~> 0.9'
|
77
77
|
s.add_dependency 'rack-config', '>= 0.9'
|
78
78
|
s.add_dependency 'uuid', '= 2.0.1'
|
79
79
|
s.add_dependency 'sequel', '= 2.6.0'
|
data/doc/curl.html
CHANGED
@@ -37,6 +37,17 @@ If you haven't already installed the gem:
|
|
37
37
|
</div>
|
38
38
|
</p>
|
39
39
|
|
40
|
+
<p>
|
41
|
+
If you already have the gem, make sure you're running the latest version (0.10.0):
|
42
|
+
<div class="code">
|
43
|
+
$ gem list cloudkit<br/>
|
44
|
+
cloudkit (0.9.1) <-- need to upgrade<br/>
|
45
|
+
$ gem update cloudkit<br/>
|
46
|
+
$ gem list cloudkit<br/>
|
47
|
+
cloudkit (0.10.0, 0.9.1) <-- 0.10.0 is now in the list
|
48
|
+
</div>
|
49
|
+
</p>
|
50
|
+
|
40
51
|
<p>
|
41
52
|
Create a rackup file named config.ru, containing these two lines of code:
|
42
53
|
<div class="code">
|
@@ -46,9 +57,9 @@ Create a rackup file named config.ru, containing these two lines of code:
|
|
46
57
|
</p>
|
47
58
|
|
48
59
|
<p>
|
49
|
-
Run the app
|
60
|
+
Run the app:
|
50
61
|
<div class="code">
|
51
|
-
$
|
62
|
+
$ rackup config.ru
|
52
63
|
</div>
|
53
64
|
</p>
|
54
65
|
|
@@ -56,13 +67,12 @@ Run the app using <a href="http://code.macournoyer.com/thin">Thin</a>:
|
|
56
67
|
CloudKit is discoverable from top to bottom. Let's see what resource collections
|
57
68
|
we're hosting:
|
58
69
|
<div class="code">
|
59
|
-
$ curl -i http://localhost:
|
70
|
+
$ curl -i http://localhost:9292/cloudkit-meta<br/>
|
60
71
|
HTTP/1.1 200 OK<br/>
|
61
72
|
ETag: "ef2f29b1834ef8c2bf0d8f1abb100177"<br/>
|
62
73
|
Cache-Control: proxy-revalidate<br/>
|
63
74
|
Content-Type: application/json<br/>
|
64
|
-
Content-Length: 20<br/>
|
65
|
-
Connection: keep-alive<br/><br/>
|
75
|
+
Content-Length: 20<br/><br/>
|
66
76
|
|
67
77
|
{"uris":["\/notes"]}
|
68
78
|
</div>
|
@@ -71,39 +81,47 @@ we're hosting:
|
|
71
81
|
<p>
|
72
82
|
See what we can do with these note resources:
|
73
83
|
<div class="code">
|
74
|
-
$ curl -i -XOPTIONS http://localhost:
|
84
|
+
$ curl -i -XOPTIONS http://localhost:9292/notes<br/>
|
75
85
|
HTTP/1.1 200 OK<br/>
|
76
86
|
Content-Length: 0<br/>
|
77
87
|
Content-Type: application/json<br/>
|
78
88
|
Allow: GET, HEAD, POST, OPTIONS<br/>
|
79
|
-
Connection: keep-alive<br/>
|
80
89
|
</div>
|
81
90
|
</p>
|
82
91
|
|
83
92
|
<p>
|
84
93
|
List the currently available notes:
|
85
94
|
<div class="code">
|
86
|
-
$ curl -i http://localhost:
|
95
|
+
$ curl -i http://localhost:9292/notes<br/>
|
87
96
|
HTTP/1.1 200 OK<br/>
|
88
|
-
ETag: "
|
97
|
+
ETag: "ffc5e6012614d759283199e67f79071b"<br/>
|
98
|
+
Link: <http://localhost:9292/notes/_resolved>; rel="http://joncrosby.me/cloudkit/1.0/rel/resolved"<br/>
|
89
99
|
Cache-Control: proxy-revalidate<br/>
|
90
100
|
Content-Type: application/json<br/>
|
91
|
-
Content-Length: 32<br/>
|
92
|
-
Connection: keep-alive<br/><br/>
|
101
|
+
Content-Length: 32<br/><br/>
|
93
102
|
|
94
103
|
{"uris":[],"total":0,"offset":0}
|
95
104
|
</div>
|
96
105
|
</p>
|
97
106
|
|
98
107
|
<p>
|
99
|
-
|
108
|
+
Along with the usual metadata, many responses also provide discovery
|
109
|
+
information via
|
110
|
+
<a href="http://www.mnot.net/drafts/draft-nottingham-http-link-header-03.txt">Link Headers</a>
|
111
|
+
as shown above. These links allow user agents to find related resources. The
|
112
|
+
purpose of the above rel="resolved" Link Header is to offer a complete representation of
|
113
|
+
all documents in a collection as an alternative to the simple list of links provided above.
|
114
|
+
We'll look at the the result of using the "resolved" URI after we have created a few resources.
|
115
|
+
</p>
|
116
|
+
|
117
|
+
<p>
|
118
|
+
Let's move on, creating a note using <a href="http://tools.ietf.org/html/rfc2616#section-9.5">POST</a>:
|
100
119
|
<div class="code">
|
101
|
-
$ curl -i -XPOST -d'{"title":"projects"}' http://localhost:
|
120
|
+
$ curl -i -XPOST -d'{"title":"projects"}' http://localhost:9292/notes<br/>
|
102
121
|
HTTP/1.1 201 Created<br/>
|
103
122
|
Cache-Control: no-cache<br/>
|
104
123
|
Content-Type: application/json<br/>
|
105
|
-
Content-Length: 159<br/>
|
106
|
-
Connection: keep-alive<br/><br/>
|
124
|
+
Content-Length: 159<br/><br/>
|
107
125
|
|
108
126
|
{<br/>
|
109
127
|
"uri":"\/notes\/0dda06f0-b134-012b-a2d8-0017f2c62348",<br/>
|
@@ -115,35 +133,14 @@ Create a note using <a href="http://tools.ietf.org/html/rfc2616#section-9.5">POS
|
|
115
133
|
</p>
|
116
134
|
|
117
135
|
<p>
|
118
|
-
|
119
|
-
<div class="code">
|
120
|
-
$ curl -i http://localhost:3000/notes<br/>
|
121
|
-
HTTP/1.1 200 OK<br/>
|
122
|
-
Last-Modified: Sun, 21 Dec 2008 02:21:52 GMT<br/>
|
123
|
-
ETag: "dd30142ff023386d2515b41fb88447a5"<br/>
|
124
|
-
Cache-Control: proxy-revalidate<br/>
|
125
|
-
Content-Type: application/json<br/>
|
126
|
-
Content-Length: 79<br/>
|
127
|
-
Connection: keep-alive<br/><br/>
|
128
|
-
|
129
|
-
{<br/>
|
130
|
-
"uris":["\/notes\/0dda06f0-b134-012b-a2d8-0017f2c62348"],<br/>
|
131
|
-
"total":1,<br/>
|
132
|
-
"offset":0<br/>
|
133
|
-
}
|
134
|
-
</div>
|
135
|
-
</p>
|
136
|
-
|
137
|
-
<p>
|
138
|
-
Create a note using <a href="http://tools.ietf.org/html/rfc2616#section-9.6">PUT</a>
|
136
|
+
Create a different note using <a href="http://tools.ietf.org/html/rfc2616#section-9.6">PUT</a>
|
139
137
|
so that we can specify its location:
|
140
138
|
<div class="code">
|
141
|
-
$ curl -i -XPUT -d'{"title":"reminders"}' http://localhost:
|
139
|
+
$ curl -i -XPUT -d'{"title":"reminders"}' http://localhost:9292/notes/abc<br/>
|
142
140
|
HTTP/1.1 201 Created<br/>
|
143
141
|
Cache-Control: no-cache<br/>
|
144
142
|
Content-Type: application/json<br/>
|
145
|
-
Content-Length: 126<br/>
|
146
|
-
Connection: keep-alive<br/><br/>
|
143
|
+
Content-Length: 126<br/><br/>
|
147
144
|
|
148
145
|
{<br/>
|
149
146
|
"uri":"\/notes\/abc",<br/>
|
@@ -157,37 +154,33 @@ so that we can specify its location:
|
|
157
154
|
<p>
|
158
155
|
View the new note:
|
159
156
|
<div class="code">
|
160
|
-
$ curl -i http://localhost:
|
157
|
+
$ curl -i http://localhost:9292/notes/abc<br/>
|
161
158
|
HTTP/1.1 200 OK<br/>
|
162
159
|
Last-Modified: Sun, 21 Dec 2008 02:25:19 GMT<br/>
|
163
160
|
ETag: "89487620-b134-012b-a2d8-0017f2c62348"<br/>
|
164
|
-
Link: <http://localhost:
|
161
|
+
Link: <http://localhost:9292/notes/abc/versions>; rel="http://joncrosby.me/cloudkit/1.0/rel/versions"<br/>
|
165
162
|
Cache-Control: proxy-revalidate<br/>
|
166
163
|
Content-Type: application/json<br/>
|
167
|
-
Content-Length: 21<br/>
|
168
|
-
Connection: keep-alive<br/><br/>
|
164
|
+
Content-Length: 21<br/><br/>
|
169
165
|
|
170
166
|
{"title":"reminders"}
|
171
167
|
</div>
|
172
168
|
</p>
|
173
169
|
|
174
170
|
<p>
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
as shown above. These links allow user agents to find related resources such as
|
179
|
-
the complete history of a document.
|
171
|
+
Once again, we see a Link header. This one lists the location of the complete history
|
172
|
+
of this particular document. This history contains all versions of the document including
|
173
|
+
the most recent. We will see it in action in a moment.
|
180
174
|
</p>
|
181
175
|
|
182
176
|
<p>
|
183
|
-
|
177
|
+
Next, attempt a careless update of our newest resource and enjoy the failure:
|
184
178
|
<div class="code">
|
185
|
-
$ curl -i -XPUT -d'{"title":"foo"}' http://localhost:
|
179
|
+
$ curl -i -XPUT -d'{"title":"foo"}' http://localhost:9292/notes/abc<br/>
|
186
180
|
HTTP/1.1 400 Bad Request<br/>
|
187
181
|
Cache-Control: no-cache<br/>
|
188
182
|
Content-Type: application/json<br/>
|
189
|
-
Content-Length: 25<br/>
|
190
|
-
Connection: keep-alive<br/><br/>
|
183
|
+
Content-Length: 25<br/><br/>
|
191
184
|
|
192
185
|
{"error":"etag required"}
|
193
186
|
</div>
|
@@ -196,7 +189,7 @@ Attempt a careless update and enjoy the failure:
|
|
196
189
|
<p>
|
197
190
|
Succeed in updating by being specific:
|
198
191
|
<div class="code">
|
199
|
-
$ curl -i -XPUT -H'If-Match:89487620-b134-012b-a2d8-0017f2c62348' -d'{"title":"foo"}' http://localhost:
|
192
|
+
$ curl -i -XPUT -H'If-Match:89487620-b134-012b-a2d8-0017f2c62348' -d'{"title":"foo"}' http://localhost:9292/notes/abc<br/>
|
200
193
|
HTTP/1.1 200 OK<br/>
|
201
194
|
Cache-Control: no-cache<br/>
|
202
195
|
Content-Type: application/json<br/>
|
@@ -221,12 +214,11 @@ created your own "abc" resource.)
|
|
221
214
|
<p>
|
222
215
|
Watch a secondary, out-of-date client fail at updating by being specific but also being stale:
|
223
216
|
<div class="code">
|
224
|
-
$ curl -i -XPUT -H'If-Match:89487620-b134-012b-a2d8-0017f2c62348' -d'{"title":"
|
217
|
+
$ curl -i -XPUT -H'If-Match:89487620-b134-012b-a2d8-0017f2c62348' -d'{"title":"bar"}' http://localhost:9292/notes/abc<br/>
|
225
218
|
HTTP/1.1 412 Precondition Failed<br/>
|
226
219
|
Cache-Control: no-cache<br/>
|
227
220
|
Content-Type: application/json<br/>
|
228
|
-
Content-Length: 31<br/>
|
229
|
-
Connection: keep-alive<br/><br/>
|
221
|
+
Content-Length: 31<br/><br/>
|
230
222
|
|
231
223
|
{"error":"precondition failed"}
|
232
224
|
</div>
|
@@ -241,17 +233,17 @@ version of the resource.
|
|
241
233
|
</p>
|
242
234
|
|
243
235
|
<p>
|
244
|
-
|
236
|
+
We can list all versions of the document using the URI tagged with rel="versions" in the
|
245
237
|
link header mentioned above, reverse sorted by Last-Modified, feed style:
|
246
238
|
<div class="code">
|
247
|
-
$ curl -i http://localhost:
|
239
|
+
$ curl -i http://localhost:9292/notes/abc/versions<br/>
|
248
240
|
HTTP/1.1 200 OK<br/>
|
249
241
|
Last-Modified: Sun, 21 Dec 2008 02:30:56 GMT<br/>
|
250
|
-
ETag: "
|
242
|
+
ETag: "28ecf6899a45d3cdd0ad82bad56991d1"<br/>
|
243
|
+
Link: <http://localhost:9292/notes/abc/versions/_resolved>; rel="http://joncrosby.me/cloudkit/1.0/rel/resolved"<br/>
|
251
244
|
Cache-Control: proxy-revalidate<br/>
|
252
245
|
Content-Type: application/json<br/>
|
253
|
-
Content-Length: 109<br/>
|
254
|
-
Connection: keep-alive<br/><br/>
|
246
|
+
Content-Length: 109<br/><br/>
|
255
247
|
|
256
248
|
{<br/>
|
257
249
|
"uris":[<br/>
|
@@ -265,14 +257,84 @@ link header mentioned above, reverse sorted by Last-Modified, feed style:
|
|
265
257
|
</p>
|
266
258
|
|
267
259
|
<p>
|
268
|
-
|
260
|
+
List all versions again, this time using the "resolved" URI from the Link header.
|
261
|
+
This effectively delivers the same information that would be obtained by first listing
|
262
|
+
the URIs, then fetching each one of them individually.
|
263
|
+
<div class="code">
|
264
|
+
$ curl -i http://localhost:9292/notes/abc/versions/_resolved<br/>
|
265
|
+
HTTP/1.1 200 OK<br/>
|
266
|
+
Last-Modified: Sun, 21 Dec 2008 02:30:56 GMT<br/>
|
267
|
+
ETag: "282819afc09d7735fd6801532c0c7033"<br/>
|
268
|
+
Link: <http://localhost:9292/notes/abc/versions>; rel="index"<br/>
|
269
|
+
Cache-Control: proxy-revalidate<br/>
|
270
|
+
Content-Type: application/json<br/>
|
271
|
+
Content-Length: 390<br/><br/>
|
272
|
+
|
273
|
+
{<br/>
|
274
|
+
"documents":[<br/>
|
275
|
+
{<br/>
|
276
|
+
"etag":"522be9f0-b135-012b-a2d8-0017f2c62348",<br/>
|
277
|
+
"last_modified":"Sun, 21 Dec 2008 02:30:56 GMT",<br/>
|
278
|
+
"document":"{\"title\":\"foo\"}",<br/>
|
279
|
+
"uri":"\/notes\/abc"<br/>
|
280
|
+
},<br/>
|
281
|
+
{<br/>
|
282
|
+
"etag":"89487620-b134-012b-a2d8-0017f2c62348",<br/>
|
283
|
+
"last_modified":"Sun, 21 Dec 2008 02:25:19 GMT",<br/>
|
284
|
+
"document":"{\"title\":\"reminders\"}",<br/>
|
285
|
+
"uri":"\/notes\/abc\/versions\/89487620-b134-012b-a2d8-0017f2c62348"}<br/>
|
286
|
+
],<br/>
|
287
|
+
"total":2,<br/>
|
288
|
+
"offset":0<br/>
|
289
|
+
}
|
290
|
+
</div>
|
291
|
+
</p>
|
292
|
+
|
293
|
+
<p>
|
294
|
+
Notice the resolved response includes a Link header pointing back to its index.
|
295
|
+
</p>
|
296
|
+
|
297
|
+
<p>
|
298
|
+
We can use this same "resolved" technique on the main "notes" listing:
|
269
299
|
<div class="code">
|
270
|
-
$ curl -i
|
300
|
+
$ curl -i http://localhost:9292/notes/_resolved<br/>
|
301
|
+
HTTP/1.1 200 OK<br/>
|
302
|
+
Last-Modified: Sun, 21 Dec 2008 02:30:56 GMT<br/>
|
303
|
+
ETag: "6628242625a7f71cce838a02deb27912"<br/>
|
304
|
+
Link: <http://localhost:9292/notes> rel="index"<br/>
|
305
|
+
Cache-Control: proxy-revalidate<br/>
|
306
|
+
Content-Type: application/json<br/>
|
307
|
+
Content-Length: 374<br/><br/>
|
308
|
+
|
309
|
+
{<br/>
|
310
|
+
"documents":[<br/>
|
311
|
+
{<br/>
|
312
|
+
"etag":"522be9f0-b135-012b-a2d8-0017f2c62348",<br/>
|
313
|
+
"last_modified":"Sun, 21 Dec 2008 02:30:56 GMT",<br/>
|
314
|
+
"document":"{\"title\":\"foo\"}",<br/>
|
315
|
+
"uri":"\/notes\/abc"<br/>
|
316
|
+
},<br/>
|
317
|
+
{<br/>
|
318
|
+
"etag":"0dda0de0-b134-012b-a2d8-0017f2c62348",<br/>
|
319
|
+
"last_modified":"Sun, 21 Dec 2008 02:21:52 GMT",<br/>
|
320
|
+
"document":"{\"title\":\"projects\"}",<br/>
|
321
|
+
"uri":"\/notes\/0dda06f0-b134-012b-a2d8-0017f2c62348"<br/>
|
322
|
+
}<br/>
|
323
|
+
],<br/>
|
324
|
+
"total":2,<br/>
|
325
|
+
"offset":0<br/>
|
326
|
+
}
|
327
|
+
</div>
|
328
|
+
</p>
|
329
|
+
|
330
|
+
<p>
|
331
|
+
Next, let's delete the our most recent document:
|
332
|
+
<div class="code">
|
333
|
+
$ curl -i -XDELETE -H'If-Match:522be9f0-b135-012b-a2d8-0017f2c62348' http://localhost:9292/notes/abc<br/>
|
271
334
|
HTTP/1.1 200 OK<br/>
|
272
335
|
Cache-Control: no-cache<br/>
|
273
336
|
Content-Type: application/json<br/>
|
274
|
-
Content-Length: 174<br/>
|
275
|
-
Connection: keep-alive<br/><br/>
|
337
|
+
Content-Length: 174<br/><br/>
|
276
338
|
|
277
339
|
{<br/>
|
278
340
|
"uri":"\/notes\/abc\/versions\/522be9f0-b135-012b-a2d8-0017f2c62348",<br/>
|
@@ -286,13 +348,12 @@ Delete the document:
|
|
286
348
|
<p>
|
287
349
|
Try to GET it again and notice the helpful <a href="http://tools.ietf.org/html/rfc2616#section-10.4.11">410</a>:
|
288
350
|
<div class="code">
|
289
|
-
$ curl -i http://localhost:
|
351
|
+
$ curl -i http://localhost:9292/notes/abc<br/>
|
290
352
|
HTTP/1.1 410 Gone<br/>
|
291
|
-
Link: <http://localhost:
|
353
|
+
Link: <http://localhost:9292/notes/abc/versions>; rel="http://joncrosby.me/cloudkit/1.0/rel/versions"<br/>
|
292
354
|
Cache-Control: no-cache<br/>
|
293
355
|
Content-Type: application/json<br/>
|
294
|
-
Content-Length: 37<br/>
|
295
|
-
Connection: keep-alive<br/><br/>
|
356
|
+
Content-Length: 37<br/><br/>
|
296
357
|
|
297
358
|
{"error":"entity previously deleted"}
|
298
359
|
</div>
|
@@ -301,14 +362,14 @@ Try to GET it again and notice the helpful <a href="http://tools.ietf.org/html/r
|
|
301
362
|
<p>
|
302
363
|
Notice the history is preserved:
|
303
364
|
<div class="code">
|
304
|
-
$ curl -i http://localhost:
|
365
|
+
$ curl -i http://localhost:9292/notes/abc/versions<br/>
|
305
366
|
HTTP/1.1 200 OK<br/>
|
306
367
|
Last-Modified: Sun, 21 Dec 2008 02:30:56 GMT<br/>
|
307
368
|
ETag: "2308ee33e953c9be41221ff7612e5217"<br/>
|
369
|
+
Link: <http://localhost:9292/notes/abc/versions/_resolved>; rel="http://joncrosby.me/cloudkit/1.0/rel/resolved"<br/>
|
308
370
|
Cache-Control: proxy-revalidate<br/>
|
309
371
|
Content-Type: application/json<br/>
|
310
|
-
Content-Length: 157<br/>
|
311
|
-
Connection: keep-alive<br/><br/>
|
372
|
+
Content-Length: 157<br/><br/>
|
312
373
|
|
313
374
|
{<br/>
|
314
375
|
"uris":[<br/>
|