restfulie 1.0.0.beta1 → 1.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|