cloudkit 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/>
|