rackful 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +30 -0
- data/RACKFUL.md +159 -0
- data/rackful.gemspec +3 -3
- metadata +8 -6
data/CHANGES.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
0.1.x
|
2
|
+
=====
|
3
|
+
The 0.1.x series is a major revision, not backward compatible with 0.0.x.
|
4
|
+
|
5
|
+
0.1.1
|
6
|
+
-----
|
7
|
+
* Fixed the gemspec file. Not everything new was properly included (including
|
8
|
+
this changelog!).
|
9
|
+
|
10
|
+
0.1.0
|
11
|
+
-----
|
12
|
+
* Complete revision of the {Rackful::HTTPStatus} exception class. From now on,
|
13
|
+
there's
|
14
|
+
a separate class for each HTTP status code, e.g. {Rackful::HTTP404NotFound}.
|
15
|
+
* {Rackful::Path}, a subclass of `String`, is used for HTTP paths. This allows
|
16
|
+
serializers, especially for hypermedia, to distinguish paths from "ordinary"
|
17
|
+
strings, and render them accordingly.
|
18
|
+
* The concept of {Rackful::Serializer Serializers} was introduced. A serializer
|
19
|
+
is an object that knows how to serialize an object to a certain media type.
|
20
|
+
* The mechanism for content negotiation has changed completely. See
|
21
|
+
{Rackful::Resource#serializer} and {Rackful::Resource::ClassMethods#best_content_type}.
|
22
|
+
* The mechanism for implementing HTTP method handlers has changed. See
|
23
|
+
{Rackful::Resource#do_METHOD} and {Rackful::Resource::ClassMethods#add_parser}.
|
24
|
+
|
25
|
+
0.0.x
|
26
|
+
=====
|
27
|
+
|
28
|
+
0.0.2
|
29
|
+
-----
|
30
|
+
* Improved documentation
|
data/RACKFUL.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
Rackful
|
2
|
+
=======
|
3
|
+
|
4
|
+
Library for creating Rackful web services
|
5
|
+
|
6
|
+
The latest documentation is always available
|
7
|
+
[here, as GitHub pages](http://pieterb.github.com/Rackful/).
|
8
|
+
|
9
|
+
Rationale
|
10
|
+
---------
|
11
|
+
|
12
|
+
Confronted with the task of implementing a Rackful web service in Ruby, I
|
13
|
+
checked out a number of existing libraries and frameworks, including
|
14
|
+
Ruby-on-Rails, and then decided to brew my own, the reason being that I couldn't
|
15
|
+
find a library or framework with all of the following properties:
|
16
|
+
|
17
|
+
* **Small** Some of these frameworks are really big. I need to get a job done in
|
18
|
+
time. If understanding the framework takes more time than writing my own, I
|
19
|
+
must at least feel confident that the framework I'm learning is more powerful
|
20
|
+
that what I can come up with by myself. Ruby-on-Rails is probably the biggest
|
21
|
+
framework out there, and it still lacks many features that are essential to
|
22
|
+
Rackful web service programming.
|
23
|
+
|
24
|
+
This library is small. You could read _all_ the source code in less than an
|
25
|
+
hour, and understand every detail.
|
26
|
+
|
27
|
+
* **No extensive tooling or code generation** Code generation has been the
|
28
|
+
subject of more than one flame-war over the years. Not much I can add to the
|
29
|
+
debate...
|
30
|
+
|
31
|
+
_...but,_ with Ruby, you shouldn't _need_ code generation!
|
32
|
+
Unless, of course, you're an ex-Java programmer and/or don't understand
|
33
|
+
meta-programming.
|
34
|
+
|
35
|
+
* **Full support for conditional requests** using `If-*:` request headers. Most
|
36
|
+
libraries' support is limited to `If-None-Match:` and `If-Modified-Since:`
|
37
|
+
headers, and only for `GET` and `HEAD` requests. For Rackful web services,
|
38
|
+
the `If-Match:` and `If-Unmodified-Since:` headers are at least as important,
|
39
|
+
particularly for unsafe methods like `PUT`, `POST`, `PATCH`, and `DELETE`.
|
40
|
+
|
41
|
+
This library fully supports the `ETag:` and `Last-Modified:` headers, and all
|
42
|
+
`If-*:` headers.
|
43
|
+
|
44
|
+
* **Resource centered** Some libraries claim Rackfulness, but at the same
|
45
|
+
time have a servet-like interface, which requires you to implement method
|
46
|
+
handles such as `doPOST(url)`. In these method handlers you have to find out
|
47
|
+
what resource is posted to, depending on the URL.
|
48
|
+
|
49
|
+
This library requires that you implement a Resource Factory which maps URIs
|
50
|
+
to resource Objects. These objects will then receive HTTP requests.
|
51
|
+
|
52
|
+
Hello World!
|
53
|
+
------------
|
54
|
+
|
55
|
+
Here's a working example of a simple Rackful server:
|
56
|
+
|
57
|
+
{include:file:example/config.ru}
|
58
|
+
|
59
|
+
This file is included in the distribution as `example/config.ru`.
|
60
|
+
If you go to the `example` directory and run `rackup`, you should see
|
61
|
+
something like this:
|
62
|
+
|
63
|
+
$> rackup
|
64
|
+
[2012-07-10 11:45:32] INFO WEBrick 1.3.1
|
65
|
+
[2012-07-10 11:45:32] INFO ruby 1.9.2 (2011-12-27) [java]
|
66
|
+
[2012-07-10 11:45:32] INFO WEBrick::HTTPServer#start: pid=5994 port=9292
|
67
|
+
|
68
|
+
Go with your browser to {http://localhost:9292/} and be greeted.
|
69
|
+
|
70
|
+
In this example, we implement `GET` and `PUT` requests for the resource at '/'. but
|
71
|
+
we get a few things for free:
|
72
|
+
|
73
|
+
### Free `OPTIONS` response:
|
74
|
+
|
75
|
+
Request:
|
76
|
+
|
77
|
+
OPTIONS / HTTP/1.1
|
78
|
+
Host: localhost:9292
|
79
|
+
|
80
|
+
Response:
|
81
|
+
|
82
|
+
HTTP/1.1 204 No Content
|
83
|
+
Allow: PUT, GET, HEAD, OPTIONS
|
84
|
+
Date: Tue, 10 Jul 2012 10:22:52 GMT
|
85
|
+
|
86
|
+
As you can see, the server accurately reports all available methods for the
|
87
|
+
resource. Notice the availability of the `HEAD` method; if you implement the
|
88
|
+
`GET` method, you'll get `HEAD` for free. It's still a good idea to explicitly
|
89
|
+
implement your own `HEAD` request handler, especially for expensive resources,
|
90
|
+
when responding to a `HEAD` request should be much more efficient than generating
|
91
|
+
a full `GET` response, and strip off the response body.
|
92
|
+
|
93
|
+
### Free conditional request handling:
|
94
|
+
|
95
|
+
Let's first get the current state of the resource, with this request:
|
96
|
+
|
97
|
+
GET / HTTP/1.1
|
98
|
+
Host: localhost:9292
|
99
|
+
|
100
|
+
Response:
|
101
|
+
|
102
|
+
HTTP/1.1 200 OK
|
103
|
+
Content-Type: text/plain
|
104
|
+
Content-Length: 12
|
105
|
+
ETag: "86fb269d190d2c85f6e0468ceca42a20"
|
106
|
+
Date: Tue, 10 Jul 2012 10:34:36 GMT
|
107
|
+
|
108
|
+
Hello world!
|
109
|
+
|
110
|
+
Now, we'd like to change the state of the resource, but only if it's still in
|
111
|
+
the state we last saw, to avoid the "lost update problem". To do that, we
|
112
|
+
produce an `If-Match:` header, with the entity tag of our last version:
|
113
|
+
|
114
|
+
PUT / HTTP/1.1
|
115
|
+
Host: localhost:9292
|
116
|
+
Content-Type: text/plain
|
117
|
+
Content-Length: 31
|
118
|
+
If-Match: "86fb269d190d2c85f6e0468ceca42a20"
|
119
|
+
|
120
|
+
All your base are belong to us.
|
121
|
+
|
122
|
+
Response:
|
123
|
+
|
124
|
+
HTTP/1.1 204 No Content
|
125
|
+
ETag: "920c1e9267f923c62b55a471c1d8a528"
|
126
|
+
Date: Tue, 10 Jul 2012 10:58:57 GMT
|
127
|
+
|
128
|
+
The response contains an `ETag:` header, with the _new_ entity tag of this
|
129
|
+
resource. When we replay this request, we get the following response:
|
130
|
+
|
131
|
+
HTTP/1.1 412 Precondition Failed
|
132
|
+
Content-Type: text/html; charset="UTF-8"
|
133
|
+
Date: Tue, 10 Jul 2012 11:06:54 GMT
|
134
|
+
|
135
|
+
[...]
|
136
|
+
<h1>HTTP/1.1 412 Precondition Failed</h1>
|
137
|
+
<p>If-Match: "86fb269d190d2c85f6e0468ceca42a20"</p>
|
138
|
+
[...]
|
139
|
+
|
140
|
+
The server returns with status <tt>412 Precondition Failed</tt>. In the HTML
|
141
|
+
response body, the server kindly points out exactly which precondition.
|
142
|
+
|
143
|
+
Further reading
|
144
|
+
---------------
|
145
|
+
* {Rackful::Server#initialize} for more information about your Resource Factory.
|
146
|
+
* {Rackful::Resource#get_etag} and {Rackful::Resource#get_last_modified} for more information on
|
147
|
+
conditional requests.
|
148
|
+
* {Rackful::Resource#do_METHOD} for more information about writing your own request
|
149
|
+
handlers.
|
150
|
+
* {Rackful::RelativeLocation} for more information about this piece of Rack middleware
|
151
|
+
which allows you to return relative and absolute paths in the `Location:`
|
152
|
+
response header, and why you'd want that.
|
153
|
+
|
154
|
+
Licensing
|
155
|
+
---------
|
156
|
+
Copyright ©2011-2012 Pieter van Beek <pieterb@sara.nl>
|
157
|
+
|
158
|
+
Licensed under the Apache License 2.0. You should have received a copy of the
|
159
|
+
license as part of this distribution.
|
data/rackful.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
|
2
2
|
|
3
3
|
# Required properties:
|
4
4
|
s.name = 'rackful'
|
5
|
-
s.version = '0.1.
|
5
|
+
s.version = '0.1.1'
|
6
6
|
s.summary = "Library for building ReSTful web services with Rack"
|
7
7
|
s.description = <<EOS
|
8
8
|
Rackful provides a minimal interface for developing ReSTful web services with
|
@@ -11,8 +11,8 @@ resource objects, which expose their state at URLs.
|
|
11
11
|
|
12
12
|
This version is NOT backward compatible with versions 0.0.x.
|
13
13
|
EOS
|
14
|
-
s.files = Dir[ '{example/*,lib/**/*}' ] +
|
15
|
-
%w( rackful.gemspec
|
14
|
+
s.files = Dir[ '{*.md,example/*,lib/**/*}' ] +
|
15
|
+
%w( rackful.gemspec mkdoc.sh )
|
16
16
|
|
17
17
|
# Optional properties:
|
18
18
|
s.author = 'Pieter van Beek'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rackful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-05 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
16
|
-
requirement: &
|
16
|
+
requirement: &70177120280540 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '1.4'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70177120280540
|
25
25
|
description: ! 'Rackful provides a minimal interface for developing ReSTful web services
|
26
26
|
with
|
27
27
|
|
@@ -38,6 +38,10 @@ executables: []
|
|
38
38
|
extensions: []
|
39
39
|
extra_rdoc_files: []
|
40
40
|
files:
|
41
|
+
- CHANGES.md
|
42
|
+
- LICENSE.md
|
43
|
+
- RACKFUL.md
|
44
|
+
- README.md
|
41
45
|
- example/config.ru
|
42
46
|
- example/config2.ru
|
43
47
|
- lib/rackful/header_spoofing.rb
|
@@ -51,8 +55,6 @@ files:
|
|
51
55
|
- lib/rackful_serializer.rb
|
52
56
|
- lib/rackful_server.rb
|
53
57
|
- rackful.gemspec
|
54
|
-
- README.md
|
55
|
-
- LICENSE.md
|
56
58
|
- mkdoc.sh
|
57
59
|
homepage: http://pieterb.github.com/Rackful/
|
58
60
|
licenses:
|