restfulie 1.0.0.beta1 → 1.0.0.beta4
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/Gemfile +8 -10
- data/Gemfile.lock +59 -85
- data/README.textile +22 -57
- data/Rakefile +1 -3
- data/lib/restfulie/client/cache/basic.rb +7 -5
- data/lib/restfulie/client/cache/restrictions.rb +2 -0
- data/lib/restfulie/client/dsl.rb +7 -22
- data/lib/restfulie/client/entry_point.rb +1 -1
- data/lib/restfulie/client/ext/link_ext.rb +11 -0
- data/lib/restfulie/client/ext/open_search_ext.rb +26 -0
- data/lib/restfulie/client/ext.rb +3 -0
- data/lib/restfulie/client/feature/base_request.rb +2 -2
- data/lib/restfulie/client/feature/cache.rb +2 -2
- data/lib/restfulie/client/feature/conneg_when_unaccepted.rb +25 -0
- data/lib/restfulie/client/feature/enhance_response.rb +2 -2
- data/lib/restfulie/client/feature/follow_request.rb +2 -2
- data/lib/restfulie/client/feature/history_request.rb +2 -2
- data/lib/restfulie/client/feature/retry_when_unavailable.rb +25 -0
- data/lib/restfulie/client/feature/serialize_body.rb +7 -4
- data/lib/restfulie/client/feature/setup_header.rb +2 -2
- data/lib/restfulie/client/feature/throw_error.rb +2 -2
- data/lib/restfulie/client/http/link_header.rb +39 -0
- data/lib/restfulie/client/http/response_holder.rb +2 -2
- data/lib/restfulie/client/stack_navigator.rb +39 -0
- data/lib/restfulie/client.rb +3 -5
- data/lib/restfulie/common.rb +5 -6
- data/lib/restfulie/server/action_controller/base.rb +1 -1
- data/lib/restfulie/server/core_ext/array.rb +1 -27
- data/lib/restfulie/server/tokamak.rb +6 -0
- data/lib/restfulie/server.rb +11 -10
- data/lib/restfulie/version.rb +1 -1
- metadata +24 -95
- data/lib/restfulie/client/ext/atom_ext.rb +0 -14
- data/lib/restfulie/client/ext/json_ext.rb +0 -16
- data/lib/restfulie/common/converter/atom/base.rb +0 -91
- data/lib/restfulie/common/converter/atom/builder.rb +0 -111
- data/lib/restfulie/common/converter/atom/helpers.rb +0 -17
- data/lib/restfulie/common/converter/atom.rb +0 -12
- data/lib/restfulie/common/converter/form_url_encoded.rb +0 -16
- data/lib/restfulie/common/converter/json/base.rb +0 -87
- data/lib/restfulie/common/converter/json/builder.rb +0 -102
- data/lib/restfulie/common/converter/json/helpers.rb +0 -17
- data/lib/restfulie/common/converter/json.rb +0 -12
- data/lib/restfulie/common/converter/open_search/descriptor.rb +0 -32
- data/lib/restfulie/common/converter/open_search.rb +0 -16
- data/lib/restfulie/common/converter/values.rb +0 -33
- data/lib/restfulie/common/converter/xml/base.rb +0 -63
- data/lib/restfulie/common/converter/xml/builder.rb +0 -113
- data/lib/restfulie/common/converter/xml/helpers.rb +0 -17
- data/lib/restfulie/common/converter/xml/link.rb +0 -30
- data/lib/restfulie/common/converter/xml/links.rb +0 -21
- data/lib/restfulie/common/converter/xml.rb +0 -14
- data/lib/restfulie/common/converter.rb +0 -43
- data/lib/restfulie/common/core_ext/hash.rb +0 -18
- data/lib/restfulie/common/core_ext.rb +0 -1
- data/lib/restfulie/common/links.rb +0 -9
- data/lib/restfulie/common/representation/atom/atom.rng +0 -597
- data/lib/restfulie/common/representation/atom/base.rb +0 -142
- data/lib/restfulie/common/representation/atom/category.rb +0 -41
- data/lib/restfulie/common/representation/atom/entry.rb +0 -59
- data/lib/restfulie/common/representation/atom/factory.rb +0 -43
- data/lib/restfulie/common/representation/atom/feed.rb +0 -110
- data/lib/restfulie/common/representation/atom/link.rb +0 -68
- data/lib/restfulie/common/representation/atom/person.rb +0 -48
- data/lib/restfulie/common/representation/atom/source.rb +0 -59
- data/lib/restfulie/common/representation/atom/tag_collection.rb +0 -38
- data/lib/restfulie/common/representation/atom/xml.rb +0 -90
- data/lib/restfulie/common/representation/atom.rb +0 -20
- data/lib/restfulie/common/representation/generic.rb +0 -22
- data/lib/restfulie/common/representation/json/base.rb +0 -27
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +0 -74
- data/lib/restfulie/common/representation/json/link.rb +0 -29
- data/lib/restfulie/common/representation/json/link_collection.rb +0 -23
- data/lib/restfulie/common/representation/json.rb +0 -13
- data/lib/restfulie/common/representation/links.rb +0 -11
- data/lib/restfulie/common/representation.rb +0 -3
- data/lib/restfulie/server/action_view/helpers.rb +0 -50
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +0 -21
- data/lib/restfulie/server/action_view/template_handlers.rb +0 -30
- data/lib/restfulie/server/action_view.rb +0 -10
data/Gemfile
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
# A sample Gemfile
|
|
2
1
|
source :gemcutter
|
|
3
|
-
#
|
|
4
|
-
gem "rails", ">= 3.0.0"
|
|
5
|
-
gem "libxml-ruby"
|
|
6
2
|
|
|
7
3
|
gem "rack-conneg"
|
|
8
|
-
gem "json_pure"
|
|
9
4
|
gem "sqlite3-ruby"
|
|
10
|
-
gem "
|
|
11
|
-
|
|
12
|
-
gem
|
|
5
|
+
gem 'tokamak', ">= 1.0.0.beta4"
|
|
6
|
+
gem 'medie', ">= 1.0.0.beta4"
|
|
7
|
+
gem 'respondie', "~> 0.9.0"
|
|
13
8
|
|
|
14
9
|
if RUBY_VERSION < "1.9"
|
|
15
10
|
gem "ruby-debug"
|
|
@@ -17,9 +12,12 @@ else
|
|
|
17
12
|
gem "ruby-debug19", :require => "ruby-debug"
|
|
18
13
|
end
|
|
19
14
|
|
|
15
|
+
group :development do
|
|
16
|
+
gem "yard"
|
|
17
|
+
end
|
|
18
|
+
|
|
20
19
|
group :test do
|
|
21
|
-
gem "
|
|
22
|
-
gem "rspec-rails", ">= 2.0.0.beta.19"
|
|
20
|
+
gem "rspec-rails", ">= 2.3.0"
|
|
23
21
|
gem "rcov"
|
|
24
22
|
gem "sinatra"
|
|
25
23
|
gem "state_machine"
|
data/Gemfile.lock
CHANGED
|
@@ -2,127 +2,101 @@ GEM
|
|
|
2
2
|
remote: http://rubygems.org/
|
|
3
3
|
specs:
|
|
4
4
|
abstract (1.0.0)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
actionpack (3.0.0)
|
|
9
|
-
activemodel (= 3.0.0)
|
|
10
|
-
activesupport (= 3.0.0)
|
|
5
|
+
actionpack (3.0.3)
|
|
6
|
+
activemodel (= 3.0.3)
|
|
7
|
+
activesupport (= 3.0.3)
|
|
11
8
|
builder (~> 2.1.2)
|
|
12
9
|
erubis (~> 2.6.6)
|
|
13
|
-
i18n (~> 0.4
|
|
10
|
+
i18n (~> 0.4)
|
|
14
11
|
rack (~> 1.2.1)
|
|
15
|
-
rack-mount (~> 0.6.
|
|
16
|
-
rack-test (~> 0.5.
|
|
12
|
+
rack-mount (~> 0.6.13)
|
|
13
|
+
rack-test (~> 0.5.6)
|
|
17
14
|
tzinfo (~> 0.3.23)
|
|
18
|
-
activemodel (3.0.
|
|
19
|
-
activesupport (= 3.0.
|
|
15
|
+
activemodel (3.0.3)
|
|
16
|
+
activesupport (= 3.0.3)
|
|
20
17
|
builder (~> 2.1.2)
|
|
21
|
-
i18n (~> 0.4
|
|
22
|
-
|
|
23
|
-
activemodel (= 3.0.0)
|
|
24
|
-
activesupport (= 3.0.0)
|
|
25
|
-
arel (~> 1.0.0)
|
|
26
|
-
tzinfo (~> 0.3.23)
|
|
27
|
-
activeresource (3.0.0)
|
|
28
|
-
activemodel (= 3.0.0)
|
|
29
|
-
activesupport (= 3.0.0)
|
|
30
|
-
activesupport (3.0.0)
|
|
31
|
-
arel (1.0.1)
|
|
32
|
-
activesupport (~> 3.0.0)
|
|
18
|
+
i18n (~> 0.4)
|
|
19
|
+
activesupport (3.0.3)
|
|
33
20
|
builder (2.1.2)
|
|
34
|
-
columnize (0.3.
|
|
21
|
+
columnize (0.3.2)
|
|
35
22
|
diff-lcs (1.1.2)
|
|
36
23
|
erubis (2.6.6)
|
|
37
24
|
abstract (>= 1.0.0)
|
|
38
|
-
fakeweb (1.
|
|
39
|
-
hoe (2.
|
|
25
|
+
fakeweb (1.3.0)
|
|
26
|
+
hoe (2.8.0)
|
|
40
27
|
rake (>= 0.8.7)
|
|
41
|
-
|
|
42
|
-
i18n (0.4.1)
|
|
28
|
+
i18n (0.5.0)
|
|
43
29
|
json_pure (1.4.6)
|
|
44
|
-
libxml-ruby (1.1.4)
|
|
45
30
|
linecache (0.43)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
31
|
+
medie (1.0.0.beta4)
|
|
32
|
+
actionpack (>= 3.0.0)
|
|
33
|
+
activesupport
|
|
34
|
+
json_pure
|
|
35
|
+
methodize
|
|
36
|
+
methodize (0.1)
|
|
37
|
+
nokogiri (1.4.4)
|
|
53
38
|
rack (1.2.1)
|
|
54
39
|
rack-conneg (0.1.4)
|
|
55
40
|
rack (>= 1.0)
|
|
56
|
-
rack-mount (0.6.
|
|
41
|
+
rack-mount (0.6.13)
|
|
57
42
|
rack (>= 1.0.0)
|
|
58
|
-
rack-test (0.5.
|
|
43
|
+
rack-test (0.5.7)
|
|
59
44
|
rack (>= 1.0)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
activesupport (= 3.0.0)
|
|
66
|
-
bundler (~> 1.0.0)
|
|
67
|
-
railties (= 3.0.0)
|
|
68
|
-
railties (3.0.0)
|
|
69
|
-
actionpack (= 3.0.0)
|
|
70
|
-
activesupport (= 3.0.0)
|
|
71
|
-
rake (>= 0.8.4)
|
|
72
|
-
thor (~> 0.14.0)
|
|
45
|
+
railties (3.0.3)
|
|
46
|
+
actionpack (= 3.0.3)
|
|
47
|
+
activesupport (= 3.0.3)
|
|
48
|
+
rake (>= 0.8.7)
|
|
49
|
+
thor (~> 0.14.4)
|
|
73
50
|
rake (0.8.7)
|
|
74
|
-
rcov (0.9.
|
|
51
|
+
rcov (0.9.9)
|
|
75
52
|
respondie (0.9.0)
|
|
76
|
-
rspec (2.
|
|
77
|
-
rspec-core (
|
|
78
|
-
rspec-expectations (
|
|
79
|
-
rspec-mocks (
|
|
80
|
-
rspec-core (2.
|
|
81
|
-
rspec-expectations (2.
|
|
82
|
-
diff-lcs (
|
|
83
|
-
rspec-mocks (2.
|
|
84
|
-
rspec-rails (2.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
53
|
+
rspec (2.3.0)
|
|
54
|
+
rspec-core (~> 2.3.0)
|
|
55
|
+
rspec-expectations (~> 2.3.0)
|
|
56
|
+
rspec-mocks (~> 2.3.0)
|
|
57
|
+
rspec-core (2.3.1)
|
|
58
|
+
rspec-expectations (2.3.0)
|
|
59
|
+
diff-lcs (~> 1.1.2)
|
|
60
|
+
rspec-mocks (2.3.0)
|
|
61
|
+
rspec-rails (2.3.1)
|
|
62
|
+
actionpack (~> 3.0)
|
|
63
|
+
activesupport (~> 3.0)
|
|
64
|
+
railties (~> 3.0)
|
|
65
|
+
rspec (~> 2.3.0)
|
|
66
|
+
ruby-debug (0.10.4)
|
|
88
67
|
columnize (>= 0.1)
|
|
89
|
-
ruby-debug-base (~> 0.10.
|
|
90
|
-
ruby-debug-base (0.10.
|
|
68
|
+
ruby-debug-base (~> 0.10.4.0)
|
|
69
|
+
ruby-debug-base (0.10.4)
|
|
91
70
|
linecache (>= 0.3)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
sqlite3-ruby (1.3.1)
|
|
71
|
+
sinatra (1.1.2)
|
|
72
|
+
rack (~> 1.1)
|
|
73
|
+
tilt (~> 1.2)
|
|
74
|
+
sqlite3-ruby (1.3.2)
|
|
97
75
|
state_machine (0.9.4)
|
|
98
76
|
test-unit (1.2.3)
|
|
99
77
|
hoe (>= 1.5.1)
|
|
100
|
-
thor (0.14.
|
|
101
|
-
|
|
102
|
-
|
|
78
|
+
thor (0.14.6)
|
|
79
|
+
tilt (1.2.1)
|
|
80
|
+
tokamak (1.1.1)
|
|
81
|
+
json_pure
|
|
82
|
+
nokogiri
|
|
103
83
|
tzinfo (0.3.23)
|
|
104
|
-
|
|
105
|
-
nokogiri (>= 1.2.0)
|
|
106
|
-
rack (>= 1.0)
|
|
107
|
-
rack-test (>= 0.5.3)
|
|
108
|
-
yard (0.5.8)
|
|
84
|
+
yard (0.6.4)
|
|
109
85
|
|
|
110
86
|
PLATFORMS
|
|
111
87
|
ruby
|
|
112
88
|
|
|
113
89
|
DEPENDENCIES
|
|
114
90
|
fakeweb
|
|
115
|
-
|
|
116
|
-
libxml-ruby
|
|
117
|
-
nokogiri
|
|
91
|
+
medie (>= 1.0.0.beta4)
|
|
118
92
|
rack-conneg
|
|
119
|
-
rails (>= 3.0.0)
|
|
120
93
|
rcov
|
|
121
|
-
respondie
|
|
122
|
-
rspec-rails (>= 2.
|
|
94
|
+
respondie (~> 0.9.0)
|
|
95
|
+
rspec-rails (>= 2.3.0)
|
|
123
96
|
ruby-debug
|
|
124
97
|
sinatra
|
|
125
98
|
sqlite3-ruby
|
|
126
99
|
state_machine
|
|
127
100
|
test-unit (= 1.2.3)
|
|
101
|
+
tokamak (>= 1.0.0.beta4)
|
|
128
102
|
yard
|
data/README.textile
CHANGED
|
@@ -1,85 +1,50 @@
|
|
|
1
1
|
h1. Web site
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
From there you can see some videos and read the "Restfulie from Scratch guide":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf.
|
|
3
|
+
"http://restfulie.caelumobjects.com":"Restfulie's site" has a lot of information on Restfulie itself
|
|
5
4
|
|
|
6
5
|
h1. Quit pretending
|
|
7
6
|
|
|
8
|
-
CRUD through HTTP is a good step forward to using resources and becoming RESTful, another step further into it is to make use of hypermedia and semantic meaningful media types: this gem allows you to do it really fast.
|
|
7
|
+
CRUD through HTTP and web services (aka Rest) in Rails is a good step forward to using resources and becoming RESTful, another step further into it is to make use of hypermedia and semantic meaningful media types: this gem allows you to do it really fast. Go go go!
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
h2. Bite me!
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Easy --> writing hypermedia and semantic meaningful media type aware clients
|
|
15
|
-
# Small -> it's not a bloated solution with a huge list of APIs
|
|
16
|
-
# HATEOAS --> clients you are unaware of will not bother if you change
|
|
17
|
-
# HATEOAS --> consumed resources will not affect your software whenever they change their flow
|
|
18
|
-
# Adaptability --> clients are able to adapt to your changes
|
|
19
|
-
|
|
20
|
-
h2. Simple server example
|
|
21
|
-
|
|
22
|
-
In the server side, all you need to do is notify inherited_resources which media types you are able to represent your resource:
|
|
11
|
+
One liners for your pleasure. First, how to let restfulie know which media types you can handle:
|
|
23
12
|
|
|
24
13
|
<pre>
|
|
25
|
-
|
|
26
|
-
include Restfulie::Server::ActionController::Base
|
|
27
|
-
|
|
14
|
+
class ItemsController < ...
|
|
28
15
|
respond_to :atom, :html, :xml, :commerce, :opensearch
|
|
29
|
-
|
|
30
|
-
def index
|
|
31
|
-
respond_with @orders = Order.all
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def show
|
|
35
|
-
respond_with @order = Order.find(params[:id])
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
16
|
+
end
|
|
39
17
|
</pre>
|
|
40
18
|
|
|
41
|
-
|
|
19
|
+
Now let's handle them all:
|
|
42
20
|
|
|
43
21
|
<pre>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
value.id = orders_url
|
|
22
|
+
def index
|
|
23
|
+
respond_with @orders = Order.all
|
|
47
24
|
end
|
|
48
|
-
|
|
49
|
-
collection.link("create", orders_url)
|
|
50
|
-
collection.members
|
|
51
|
-
end
|
|
52
25
|
</pre>
|
|
53
26
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
h2. Simple client example
|
|
57
|
-
|
|
58
|
-
The following example is a partial REST client implementation that navigates through some relations:
|
|
27
|
+
And what is the *first* difference between simple web services with Rails and a REST architecture? Let's add hypermedia to the game:
|
|
59
28
|
|
|
60
29
|
<pre>
|
|
61
|
-
order
|
|
62
|
-
order.
|
|
63
|
-
|
|
64
|
-
puts receipt.id
|
|
30
|
+
memeber(@order) do |order|
|
|
31
|
+
order.link "payment", payment_url(order)
|
|
32
|
+
end
|
|
65
33
|
</pre>
|
|
66
34
|
|
|
67
|
-
|
|
35
|
+
There you go, hypermedia, on the fly. You can also throw in link headers and much more fun for your life when maintaining your services. Lets grab it and navigate!
|
|
68
36
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"You can also download a full example of a REST based agent and server":http://github.com/caelum/restfulie/tree/master/full-examples/rest_from_scratch/ using Restfulie, according to the Rest Architecture Maturity Model.
|
|
37
|
+
<pre>
|
|
38
|
+
response = Restfulie.at('http://localhost:3030/orders').get
|
|
39
|
+
puts response.code
|
|
74
40
|
|
|
75
|
-
|
|
41
|
+
orders = response.resource
|
|
42
|
+
response = orders.link(payment).follow.post {creditcard => 4444}
|
|
43
|
+
</pre>
|
|
76
44
|
|
|
77
|
-
|
|
45
|
+
That was it for your first hypermedia introduction with Restfulie. Now its time for the real deal.
|
|
78
46
|
|
|
79
|
-
|
|
80
|
-
* "Official website":http://restfulie.caelumobjects.com
|
|
81
|
-
* "How-tos":http://restfulie.caelumobjects.com/caelumobjects-restful-rails.pdf
|
|
82
|
-
* "Buying through Rest: Rest to the enterprise (video)":http://guilhermesilveira.wordpress.com/2010/04/13/buying-through-rest-applying-rest-to-the-enterprise/
|
|
47
|
+
Download it, install it, use it, ask questions in the mailing list and read the documentation on Restfulie's website!
|
|
83
48
|
|
|
84
49
|
h2. Installing
|
|
85
50
|
|
data/Rakefile
CHANGED
|
@@ -11,7 +11,7 @@ require File.expand_path('lib/restfulie')
|
|
|
11
11
|
GEM = "restfulie"
|
|
12
12
|
GEM_VERSION = Restfulie::VERSION
|
|
13
13
|
SUMMARY = "Hypermedia aware resource based library in ruby (client side) and ruby on rails (server side)."
|
|
14
|
-
AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon,
|
|
14
|
+
AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Everton Ribeiro, George Guimaraes, Paulo Ahagon, and many more!"
|
|
15
15
|
EMAIL = "guilherme.silveira@caelum.com.br"
|
|
16
16
|
HOMEPAGE = "http://restfulie.caelumobjects.com"
|
|
17
17
|
|
|
@@ -23,8 +23,6 @@ spec = Gem::Specification.new do |s|
|
|
|
23
23
|
s.require_paths = ['lib']
|
|
24
24
|
s.files = FileList['lib/**/*.rb', '[A-Z]*', 'lib/**/*.rng'].to_a
|
|
25
25
|
s.add_dependency("nokogiri", [">= 1.4.2"])
|
|
26
|
-
s.add_dependency("actionpack", [">= 2.3.2"])
|
|
27
|
-
s.add_dependency("activesupport", [">= 2.3.2"])
|
|
28
26
|
s.add_dependency("json_pure", [">= 1.2.4"])
|
|
29
27
|
|
|
30
28
|
s.author = AUTHOR
|
|
@@ -16,7 +16,6 @@ module Restfulie::Client::Cache
|
|
|
16
16
|
|
|
17
17
|
def get(key, request)
|
|
18
18
|
|
|
19
|
-
# debugger
|
|
20
19
|
response = cache_get(key, request)
|
|
21
20
|
return nil if response.nil?
|
|
22
21
|
|
|
@@ -34,6 +33,13 @@ module Restfulie::Client::Cache
|
|
|
34
33
|
cache.clear
|
|
35
34
|
end
|
|
36
35
|
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
# allows you to redefine the cache store
|
|
39
|
+
def cache
|
|
40
|
+
Restfulie::Client.cache_store
|
|
41
|
+
end
|
|
42
|
+
|
|
37
43
|
private
|
|
38
44
|
|
|
39
45
|
# allows response enhancement when the cache was hit with it
|
|
@@ -68,9 +74,5 @@ module Restfulie::Client::Cache
|
|
|
68
74
|
nil
|
|
69
75
|
end
|
|
70
76
|
|
|
71
|
-
def cache
|
|
72
|
-
Restfulie::Client.cache_store
|
|
73
|
-
end
|
|
74
|
-
|
|
75
77
|
end
|
|
76
78
|
end
|
data/lib/restfulie/client/dsl.rb
CHANGED
|
@@ -13,9 +13,9 @@ module Restfulie::Client
|
|
|
13
13
|
request :follow_request
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def request(what)
|
|
16
|
+
def request(what, *args)
|
|
17
17
|
req = "Restfulie::Client::Feature::#{what.to_s.classify}".constantize
|
|
18
|
-
@requests << req
|
|
18
|
+
@requests << {:type => req, :args => args}
|
|
19
19
|
self
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -32,7 +32,7 @@ module Restfulie::Client
|
|
|
32
32
|
end
|
|
33
33
|
if Restfulie::Client::Feature.const_defined? "#{sym.to_s.classify}Request"
|
|
34
34
|
loaded = true
|
|
35
|
-
request "#{sym.to_s}Request"
|
|
35
|
+
request "#{sym.to_s}Request", *args
|
|
36
36
|
end
|
|
37
37
|
if loaded
|
|
38
38
|
self
|
|
@@ -42,25 +42,10 @@ module Restfulie::Client
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def request_flow(env = {})
|
|
45
|
-
|
|
45
|
+
Restfulie::Common::Logger.logger.debug "ready to execute request using stack #{@requests}"
|
|
46
|
+
StackNavigator.new(@requests).continue(self, env)
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
class Parser
|
|
51
|
-
|
|
52
|
-
def initialize(stack)
|
|
53
|
-
@stack = stack.dup
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def continue(request, response, env)
|
|
57
|
-
current = @stack.pop
|
|
58
|
-
if current.nil?
|
|
59
|
-
return response
|
|
60
|
-
end
|
|
61
|
-
filter = current.new
|
|
62
|
-
filter.execute(self, request, response, env)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
end
|
|
49
|
+
end
|
|
50
|
+
|
|
66
51
|
end
|
|
@@ -5,7 +5,7 @@ module Restfulie
|
|
|
5
5
|
module HTTP::RecipeModule
|
|
6
6
|
def recipe(converter_sym, options={}, &block)
|
|
7
7
|
raise 'Undefined block' unless block_given?
|
|
8
|
-
converter = "
|
|
8
|
+
converter = "Tokamak::#{converter_sym.to_s.camelize}".constantize
|
|
9
9
|
converter.describe_recipe(options[:name], &block)
|
|
10
10
|
end
|
|
11
11
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Medie
|
|
2
|
+
module OpenSearch
|
|
3
|
+
class Descriptor
|
|
4
|
+
|
|
5
|
+
def use(content_type)
|
|
6
|
+
uri = urls.find do |url|
|
|
7
|
+
url["type"]==content_type
|
|
8
|
+
end
|
|
9
|
+
return nil if uri.nil?
|
|
10
|
+
|
|
11
|
+
base_uri, params_pattern = extract_uri(uri)
|
|
12
|
+
Restfulie.at(base_uri).accepts(content_type).open_search.with_pattern(params_pattern)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
def extract_uri(uri)
|
|
17
|
+
uri = uri["template"]
|
|
18
|
+
interrogation = uri.index("?")
|
|
19
|
+
params = uri[interrogation+1..uri.size]
|
|
20
|
+
base_uri = uri[0..interrogation-1]
|
|
21
|
+
[base_uri, params]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class Restfulie::Client::Feature::BaseRequest
|
|
2
2
|
|
|
3
|
-
def execute(flow, request,
|
|
3
|
+
def execute(flow, request, env)
|
|
4
4
|
request!(request.verb, request.host, request.path, request, flow, env)
|
|
5
5
|
end
|
|
6
6
|
|
|
@@ -24,7 +24,7 @@ class Restfulie::Client::Feature::BaseRequest
|
|
|
24
24
|
response = e
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
response
|
|
28
28
|
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
class Restfulie::Client::Feature::Cache
|
|
2
2
|
|
|
3
|
-
def execute(flow, request,
|
|
3
|
+
def execute(flow, request, env)
|
|
4
4
|
found = Restfulie::Client.cache_provider.get([request.host, request.path], request)
|
|
5
5
|
return found if found
|
|
6
6
|
|
|
7
|
-
resp = flow.continue(request,
|
|
7
|
+
resp = flow.continue(request, env)
|
|
8
8
|
if resp.kind_of?(Exception)
|
|
9
9
|
resp
|
|
10
10
|
else
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Retries marshalling to an acceptable media type if
|
|
2
|
+
# the server returns with 406: content negotiation. This means looking for
|
|
3
|
+
# another media type that both server and client
|
|
4
|
+
# understands, picking its converter and using it
|
|
5
|
+
# to marshal the original payload again.
|
|
6
|
+
#
|
|
7
|
+
# To use it, load it in your dsl:
|
|
8
|
+
# Restfulie.at("http://localhost:3000/product/2").conneg_when_unaccepted.get
|
|
9
|
+
module Restfulie::Client::Feature
|
|
10
|
+
class ConnegWhenUnaccepted
|
|
11
|
+
|
|
12
|
+
def execute(chain, request, env)
|
|
13
|
+
resp = chain.continue(request, env)
|
|
14
|
+
return resp if resp.code.to_i!=406
|
|
15
|
+
|
|
16
|
+
accept = Medie.registry.for(resp.headers["Accept"])
|
|
17
|
+
return resp if accept.nil?
|
|
18
|
+
|
|
19
|
+
request.with("Content-type", accept)
|
|
20
|
+
env = env.dup.merge(:body => env[:payload])
|
|
21
|
+
Restfulie::Client::Feature::SerializeBody.new.execute(chain, request, env)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Restfulie::Client::Feature
|
|
2
2
|
class EnhanceResponse
|
|
3
|
-
def execute(flow, request,
|
|
4
|
-
resp = flow.continue(request,
|
|
3
|
+
def execute(flow, request, env)
|
|
4
|
+
resp = flow.continue(request, env)
|
|
5
5
|
unless resp.kind_of? ::Restfulie::Client::HTTP::ResponseHolder
|
|
6
6
|
resp.extend(::Restfulie::Client::HTTP::ResponseHolder)
|
|
7
7
|
resp.results_from request, resp
|
|
@@ -12,8 +12,8 @@ class Restfulie::Client::Feature::FollowRequest
|
|
|
12
12
|
self
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def execute(flow, request,
|
|
16
|
-
resp = flow.continue(request,
|
|
15
|
+
def execute(flow, request, env)
|
|
16
|
+
resp = flow.continue(request, env)
|
|
17
17
|
if !resp.respond_to?(:code)
|
|
18
18
|
return resp
|
|
19
19
|
end
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
#
|
|
11
11
|
class Restfulie::Client::Feature::HistoryRequest
|
|
12
12
|
|
|
13
|
-
def execute(flow, request,
|
|
14
|
-
resp = flow.continue(request,
|
|
13
|
+
def execute(flow, request, env)
|
|
14
|
+
resp = flow.continue(request, env)
|
|
15
15
|
request.make_snapshot(request)
|
|
16
16
|
resp
|
|
17
17
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Adds support to retrying a request if the result is 503.
|
|
2
|
+
#
|
|
3
|
+
# To use it, load it in your dsl:
|
|
4
|
+
# Restfulie.at("http://localhost:3000/product/2").retry_when_unavailable.get
|
|
5
|
+
module Restfulie::Client::Feature
|
|
6
|
+
class RetryWhenUnavailable
|
|
7
|
+
|
|
8
|
+
def execute(chain, request, env)
|
|
9
|
+
resp = chain.continue(request, env)
|
|
10
|
+
if should_retry?(resp, env)
|
|
11
|
+
resp = chain.continue(request, env)
|
|
12
|
+
end
|
|
13
|
+
resp
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
# extension point that allows you to redefine
|
|
18
|
+
# when a request should be retried
|
|
19
|
+
def should_retry?(response, env)
|
|
20
|
+
response.code.to_i == 503
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
# Feature responsible for marshalling the entity into the request body.
|
|
2
|
+
# It will use the request content type header to select the proper marshaller using Medie.
|
|
1
3
|
class Restfulie::Client::Feature::SerializeBody
|
|
2
4
|
|
|
3
|
-
def execute(flow, request,
|
|
5
|
+
def execute(flow, request, env = {})
|
|
4
6
|
|
|
5
7
|
if should_have_payload?(request.verb)
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
env = env.dup
|
|
10
|
+
payload = env[:payload] = env[:body]
|
|
8
11
|
if payload && !(payload.kind_of?(String) && payload.empty?)
|
|
9
12
|
type = request.headers['Content-Type']
|
|
10
13
|
raise Restfulie::Common::Error::RestfulieError, "Missing content type related to the data to be submitted" unless type
|
|
11
14
|
|
|
12
|
-
marshaller =
|
|
15
|
+
marshaller = Medie.registry.for(type)
|
|
13
16
|
raise Restfulie::Common::Error::RestfulieError, "Missing content type for #{type} related to the data to be submitted" unless marshaller
|
|
14
17
|
|
|
15
18
|
rel = request.respond_to?(:rel) ? request.rel : ""
|
|
@@ -18,7 +21,7 @@ class Restfulie::Client::Feature::SerializeBody
|
|
|
18
21
|
|
|
19
22
|
end
|
|
20
23
|
|
|
21
|
-
flow.continue(request,
|
|
24
|
+
flow.continue(request, env)
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
protected
|
|
@@ -2,7 +2,7 @@ module Restfulie::Client::Feature
|
|
|
2
2
|
|
|
3
3
|
class SetupHeader
|
|
4
4
|
|
|
5
|
-
def execute(flow, request,
|
|
5
|
+
def execute(flow, request, env)
|
|
6
6
|
headers = request.default_headers.dup.merge(request.headers)
|
|
7
7
|
host = request.host
|
|
8
8
|
if host.user || host.password
|
|
@@ -14,7 +14,7 @@ module Restfulie::Client::Feature
|
|
|
14
14
|
# gs: this should not be overriden, do it in some other way
|
|
15
15
|
request.headers = headers
|
|
16
16
|
|
|
17
|
-
flow.continue(request,
|
|
17
|
+
flow.continue(request, env)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
end
|