restfulie 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +21 -0
- data/README.textile +10 -9
- data/Rakefile +12 -5
- data/lib/restfulie/client/base.rb +10 -6
- data/lib/restfulie/client/http/adapter.rb +48 -33
- data/lib/restfulie/client/http/atom_ext.rb +3 -68
- data/lib/restfulie/client/http/core_ext/http.rb +19 -0
- data/lib/restfulie/client/http/core_ext.rb +6 -0
- data/lib/restfulie/client/http/error.rb +3 -6
- data/lib/restfulie/client/http/marshal.rb +35 -49
- data/lib/restfulie/client/http/xml_ext.rb +7 -0
- data/lib/restfulie/client/http.rb +2 -2
- data/lib/restfulie/client/mikyung/concatenator.rb +15 -0
- data/lib/restfulie/client/mikyung/core.rb +44 -0
- data/lib/restfulie/client/mikyung/languages.rb +29 -0
- data/lib/restfulie/client/mikyung/rest_process_model.rb +114 -0
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +32 -0
- data/lib/restfulie/client/mikyung/then_condition.rb +33 -0
- data/lib/restfulie/client/mikyung/when_condition.rb +53 -0
- data/lib/restfulie/client/mikyung.rb +19 -0
- data/lib/restfulie/client.rb +1 -0
- data/lib/restfulie/common/converter/atom/builder.rb +109 -0
- data/lib/restfulie/common/converter/atom/helpers.rb +9 -0
- data/lib/restfulie/common/converter/atom.rb +87 -0
- data/lib/restfulie/common/converter/values.rb +29 -0
- data/lib/restfulie/common/converter.rb +11 -0
- data/lib/restfulie/common/core_ext/proc.rb +48 -0
- data/lib/restfulie/common/core_ext.rb +5 -0
- data/lib/restfulie/common/errors.rb +6 -0
- data/lib/restfulie/common/representation/atom/atom.rng +597 -0
- data/lib/restfulie/common/representation/atom/base.rb +375 -0
- data/lib/restfulie/common/representation/atom/entry.rb +107 -0
- data/lib/restfulie/common/representation/atom/feed.rb +106 -0
- data/lib/restfulie/common/representation/atom.rb +43 -33
- data/lib/restfulie/common/representation/json.rb +1 -2
- data/lib/restfulie/common/representation/xml.rb +209 -23
- data/lib/restfulie/common/representation.rb +0 -1
- data/lib/restfulie/common.rb +2 -3
- data/lib/restfulie/server/action_controller/base.rb +21 -2
- data/lib/restfulie/server/action_controller/params_parser.rb +16 -16
- data/lib/restfulie/server/action_controller/restful_responder.rb +3 -3
- data/lib/restfulie/server/action_controller/routing/patch.rb +6 -0
- data/lib/restfulie/server/action_view/helpers.rb +8 -8
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +3 -2
- data/lib/restfulie/server/core_ext/array.rb +13 -12
- metadata +51 -34
- data/lib/restfulie/client/http/link.rb +0 -39
- data/lib/restfulie/client/http/xml.rb +0 -4
- data/lib/restfulie/common/builder/builder_base.rb +0 -73
- data/lib/restfulie/common/builder/helpers.rb +0 -22
- data/lib/restfulie/common/builder/marshalling/atom.rb +0 -197
- data/lib/restfulie/common/builder/marshalling/base.rb +0 -12
- data/lib/restfulie/common/builder/marshalling/json.rb +0 -2
- data/lib/restfulie/common/builder/marshalling/xml.rb +0 -183
- data/lib/restfulie/common/builder/marshalling.rb +0 -16
- data/lib/restfulie/common/builder/rules/collection_rule.rb +0 -10
- data/lib/restfulie/common/builder/rules/custom_attributes.rb +0 -24
- data/lib/restfulie/common/builder/rules/link.rb +0 -20
- data/lib/restfulie/common/builder/rules/links.rb +0 -9
- data/lib/restfulie/common/builder/rules/member_rule.rb +0 -8
- data/lib/restfulie/common/builder/rules/namespace.rb +0 -35
- data/lib/restfulie/common/builder/rules/rules_base.rb +0 -77
- data/lib/restfulie/common/builder.rb +0 -17
- data/lib/vendor/atom/configuration.rb +0 -24
- data/lib/vendor/atom/pub.rb +0 -250
- data/lib/vendor/atom/xml/parser.rb +0 -373
- data/lib/vendor/atom.rb +0 -771
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# A sample Gemfile
|
2
|
+
source :gemcutter
|
3
|
+
#
|
4
|
+
gem "rails"
|
5
|
+
gem "libxml-ruby"
|
6
|
+
|
7
|
+
|
8
|
+
gem "rack-conneg"
|
9
|
+
gem "responders_backport"
|
10
|
+
gem "json_pure"
|
11
|
+
gem "sqlite3-ruby"
|
12
|
+
gem "yard"
|
13
|
+
gem "ruby-debug"
|
14
|
+
|
15
|
+
group :test do
|
16
|
+
gem "nokogiri"
|
17
|
+
gem "rspec-rails"
|
18
|
+
gem "rcov"
|
19
|
+
gem "sinatra"
|
20
|
+
end
|
21
|
+
|
data/README.textile
CHANGED
@@ -50,10 +50,13 @@ In the server side, all you need to do is notify inherited_resources which media
|
|
50
50
|
That's it. Restfulie will take care of rendering a valid representation according to content negotiation. You can configure the rendering process through a custom tokamak view:
|
51
51
|
|
52
52
|
<pre>
|
53
|
-
|
54
|
-
collection.
|
55
|
-
|
56
|
-
|
53
|
+
collection(@orders) do |collection|
|
54
|
+
collection.values do |value|
|
55
|
+
value.id = orders_url
|
56
|
+
end
|
57
|
+
|
58
|
+
collection.link("create", orders_url)
|
59
|
+
collection.members
|
57
60
|
end
|
58
61
|
</pre>
|
59
62
|
|
@@ -95,13 +98,11 @@ gem install restfulie
|
|
95
98
|
|
96
99
|
h2. Building the project
|
97
100
|
|
98
|
-
If you want to build the project and run its tests, remember to install all (client and server) required
|
101
|
+
If you want to build the project and run its tests, remember to install all (client and server) required gem.
|
102
|
+
"Bundler":http://gembundler.com/ is required to easily manage dependencies
|
99
103
|
|
100
104
|
<pre>
|
101
|
-
|
102
|
-
gem install responders_backport
|
103
|
-
gem install json_pure
|
104
|
-
gem install sqlite3-ruby
|
105
|
+
bundle install
|
105
106
|
</pre>
|
106
107
|
|
107
108
|
<script type="text/javascript">
|
data/Rakefile
CHANGED
@@ -6,19 +6,21 @@ require 'spec/rake/spectask'
|
|
6
6
|
require 'rake/rdoctask'
|
7
7
|
|
8
8
|
GEM = "restfulie"
|
9
|
-
GEM_VERSION = "0.
|
9
|
+
GEM_VERSION = "0.8.0"
|
10
10
|
SUMMARY = "Hypermedia aware resource based library in ruby (client side) and ruby on rails (server side)."
|
11
|
-
AUTHOR = "Guilherme Silveira, Caue Guerra"
|
11
|
+
AUTHOR = "Guilherme Silveira, Caue Guerra, Luis Cipriani, Éverton Ribeiro, George Guimarães, Paulo Ahagon"
|
12
12
|
EMAIL = "guilherme.silveira@caelum.com.br"
|
13
13
|
HOMEPAGE = "http://restfulie.caelumobjects.com"
|
14
14
|
|
15
|
+
|
15
16
|
spec = Gem::Specification.new do |s|
|
16
17
|
s.name = GEM
|
17
18
|
s.version = GEM_VERSION
|
18
19
|
s.platform = Gem::Platform::RUBY
|
19
20
|
s.summary = SUMMARY
|
20
21
|
s.require_paths = ['lib']
|
21
|
-
s.files = FileList['lib/**/*.rb', '[A-Z]*'].to_a
|
22
|
+
s.files = FileList['lib/**/*.rb', '[A-Z]*', 'lib/**/*.rng'].to_a
|
23
|
+
s.add_dependency("nokogiri", [">= 1.4.2"])
|
22
24
|
s.add_dependency("actionpack", [">= 2.3.2"])
|
23
25
|
s.add_dependency("activesupport", [">= 2.3.2"])
|
24
26
|
s.add_dependency("responders_backport", ["~> 0.1.0"])
|
@@ -31,7 +33,8 @@ end
|
|
31
33
|
|
32
34
|
namespace :test do
|
33
35
|
def execute_process(name)
|
34
|
-
sh "ruby ./spec/units/client/#{name}.rb &"
|
36
|
+
sh "ruby ./spec/units/client/#{name}.rb &"
|
37
|
+
sleep 15
|
35
38
|
%x(ps -ef | grep #{name}).split[1]
|
36
39
|
end
|
37
40
|
def process(name)
|
@@ -82,6 +85,10 @@ namespace :test do
|
|
82
85
|
t.rcov = true
|
83
86
|
t.rcov_opts = ["-e", "/Library*", "-e", "~/.rvm", "-e", "spec", "-i", "bin"]
|
84
87
|
end
|
88
|
+
desc 'Run coverage test with fake server'
|
89
|
+
task :run do
|
90
|
+
start_server_and_invoke_test('test:rcov:rcov')
|
91
|
+
end
|
85
92
|
end
|
86
93
|
|
87
94
|
namespace :run do
|
@@ -120,7 +127,7 @@ begin
|
|
120
127
|
t.files = ['lib/restfulie/**/*.rb', 'README.textile'] # optional
|
121
128
|
# t.options = ['--any', '--extra', '--opts'] # optional
|
122
129
|
end
|
123
|
-
rescue; end
|
130
|
+
rescue LoadError; end
|
124
131
|
|
125
132
|
desc "Install the gem locally"
|
126
133
|
task :install => [:package] do
|
@@ -4,6 +4,12 @@ module Restfulie::Client#:nodoc
|
|
4
4
|
include HTTP::RequestMarshaller
|
5
5
|
extend self
|
6
6
|
|
7
|
+
def recipe(converter_sym, options={}, &block)
|
8
|
+
raise 'Undefined block' unless block_given?
|
9
|
+
converter = "Restfulie::Common::Converter::#{converter_sym.to_s.camelize}".constantize
|
10
|
+
converter.describe_recipe(options[:name], &block)
|
11
|
+
end
|
12
|
+
|
7
13
|
@resources_configurations = {}
|
8
14
|
def configuration_of(resource_name)
|
9
15
|
@resources_configurations[resource_name]
|
@@ -16,16 +22,12 @@ module Restfulie::Client#:nodoc
|
|
16
22
|
|
17
23
|
def retrieve(resource_name)
|
18
24
|
returning Object.new do |resource|
|
19
|
-
|
25
|
+
resource.extend(Base)
|
20
26
|
resource.configure
|
21
27
|
end
|
22
28
|
end
|
23
29
|
|
24
30
|
end
|
25
|
-
class NilEntryPoint
|
26
|
-
include Restfulie::Client::EntryPoint
|
27
|
-
# extend self
|
28
|
-
end
|
29
31
|
|
30
32
|
module Base
|
31
33
|
include HTTP::RequestMarshaller
|
@@ -59,8 +61,10 @@ end
|
|
59
61
|
|
60
62
|
# Shortcut to Restfulie::Client::EntryPoint
|
61
63
|
module Restfulie
|
64
|
+
extend Restfulie::Client::EntryPoint
|
65
|
+
|
62
66
|
def self.at(uri)
|
63
|
-
Client::
|
67
|
+
Object.new.send(:extend, Restfulie::Client::EntryPoint).at(uri)
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
@@ -9,21 +9,15 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
9
9
|
attr_reader :code
|
10
10
|
attr_reader :body
|
11
11
|
attr_reader :headers
|
12
|
-
attr_reader :request
|
13
12
|
|
14
|
-
def initialize(method, path, code, body, headers
|
13
|
+
def initialize(method, path, code, body, headers)
|
15
14
|
@method = method
|
16
15
|
@path = path
|
17
16
|
@code = code
|
18
17
|
@body = body
|
19
18
|
@headers = headers
|
20
|
-
@request = request
|
21
19
|
end
|
22
20
|
|
23
|
-
def parse
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
21
|
end
|
28
22
|
|
29
23
|
#=ResponseHandler
|
@@ -81,11 +75,11 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
81
75
|
# *<tt>path: '/posts'</tt>
|
82
76
|
# *<tt>http_response</tt>
|
83
77
|
#
|
84
|
-
def self.handle(method, path, http_response
|
78
|
+
def self.handle(method, path, http_response)
|
85
79
|
response_class = @@response_handlers[http_response.code.to_i] || Response
|
86
80
|
headers = {}
|
87
81
|
http_response.header.each { |k, v| headers[k] = v }
|
88
|
-
response_class.new( method, path, http_response.code.to_i, http_response.body, headers
|
82
|
+
response_class.new( method, path, http_response.code.to_i, http_response.body, headers)
|
89
83
|
end
|
90
84
|
|
91
85
|
end
|
@@ -121,14 +115,14 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
121
115
|
|
122
116
|
#GET HTTP verb without {Error}
|
123
117
|
# * <tt>path: '/posts'</tt>
|
124
|
-
# * <tt>headers: {'
|
118
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
125
119
|
def get(path, *args)
|
126
120
|
request(:get, path, *args)
|
127
121
|
end
|
128
122
|
|
129
123
|
#HEAD HTTP verb without {Error}
|
130
124
|
# * <tt>path: '/posts'</tt>
|
131
|
-
# * <tt>headers: {'
|
125
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
132
126
|
def head(path, *args)
|
133
127
|
request(:head, path, *args)
|
134
128
|
end
|
@@ -136,36 +130,44 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
136
130
|
#POST HTTP verb without {Error}
|
137
131
|
# * <tt>path: '/posts'</tt>
|
138
132
|
# * <tt>payload: 'some text'</tt>
|
139
|
-
# * <tt>headers: {'
|
133
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
140
134
|
def post(path, payload, *args)
|
141
135
|
request(:post, path, payload, *args)
|
142
136
|
end
|
137
|
+
|
138
|
+
#PATCH HTTP verb without {Error}
|
139
|
+
# * <tt>path: '/posts'</tt>
|
140
|
+
# * <tt>payload: 'some text'</tt>
|
141
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
142
|
+
def patch(path, payload, *args)
|
143
|
+
request(:patch, path, payload, *args)
|
144
|
+
end
|
143
145
|
|
144
146
|
#PUT HTTP verb without {Error}
|
145
147
|
# * <tt>path: '/posts'</tt>
|
146
148
|
# * <tt>payload: 'some text'</tt>
|
147
|
-
# * <tt>headers: {'
|
149
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
148
150
|
def put(path, payload, *args)
|
149
151
|
request(:put, path, payload, *args)
|
150
152
|
end
|
151
153
|
|
152
154
|
#DELETE HTTP verb without {Error}
|
153
155
|
# * <tt>path: '/posts'</tt>
|
154
|
-
# * <tt>headers: {'
|
156
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
155
157
|
def delete(path, *args)
|
156
158
|
request(:delete, path, *args)
|
157
159
|
end
|
158
160
|
|
159
161
|
#GET HTTP verb {Error}
|
160
162
|
# * <tt>path: '/posts'</tt>
|
161
|
-
# * <tt>headers: {'
|
163
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
162
164
|
def get!(path, *args)
|
163
165
|
request!(:get, path, *args)
|
164
166
|
end
|
165
167
|
|
166
168
|
#HEAD HTTP verb {Error}
|
167
169
|
# * <tt>path: '/posts'</tt>
|
168
|
-
# * <tt>headers: {'
|
170
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
169
171
|
def head!(path, *args)
|
170
172
|
request!(:head, path, *args)
|
171
173
|
end
|
@@ -173,22 +175,30 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
173
175
|
#POST HTTP verb {Error}
|
174
176
|
# * <tt>path: '/posts'</tt>
|
175
177
|
# * <tt>payload: 'some text'</tt>
|
176
|
-
# * <tt>headers: {'
|
178
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
177
179
|
def post!(path, payload, *args)
|
178
180
|
request!(:post, path, payload, *args)
|
179
181
|
end
|
182
|
+
|
183
|
+
#PATCH HTTP verb {Error}
|
184
|
+
# * <tt>path: '/posts'</tt>
|
185
|
+
# * <tt>payload: 'some text'</tt>
|
186
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
187
|
+
def patch!(path, payload, *args)
|
188
|
+
request!(:patch, path, payload, *args)
|
189
|
+
end
|
180
190
|
|
181
191
|
#PUT HTTP verb {Error}
|
182
192
|
# * <tt>path: '/posts'</tt>
|
183
193
|
# * <tt>payload: 'some text'</tt>
|
184
|
-
# * <tt>headers: {'
|
194
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
185
195
|
def put!(path, payload, *args)
|
186
196
|
request!(:put, path, payload, *args)
|
187
197
|
end
|
188
198
|
|
189
199
|
#DELETE HTTP verb {Error}
|
190
200
|
# * <tt>path: '/posts'</tt>
|
191
|
-
# * <tt>headers: {'
|
201
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
192
202
|
def delete!(path, *args)
|
193
203
|
request!(:delete, path, *args)
|
194
204
|
end
|
@@ -196,7 +206,7 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
196
206
|
#Executes a request against your server and return a response instance without {Error}
|
197
207
|
# * <tt>method: :get,:post,:delete,:head,:put</tt>
|
198
208
|
# * <tt>path: '/posts'</tt>
|
199
|
-
# * <tt>args: payload: 'some text' and/or headers: {'
|
209
|
+
# * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
200
210
|
def request(method, path, *args)
|
201
211
|
request!(method, path, *args)
|
202
212
|
rescue Error::RESTError => se
|
@@ -206,7 +216,7 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
206
216
|
#Executes a request against your server and return a response instance.
|
207
217
|
# * <tt>method: :get,:post,:delete,:head,:put</tt>
|
208
218
|
# * <tt>path: '/posts'</tt>
|
209
|
-
# * <tt>args: payload: 'some text' and/or headers: {'
|
219
|
+
# * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
210
220
|
def request!(method, path, *args)
|
211
221
|
headers = default_headers.merge(args.extract_options!)
|
212
222
|
unless @host.user.blank? && @host.password.blank?
|
@@ -217,10 +227,9 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
217
227
|
|
218
228
|
::Restfulie::Common::Logger.logger.info(request_to_s(method, path, *args)) if ::Restfulie::Common::Logger.logger
|
219
229
|
begin
|
220
|
-
|
221
|
-
response = ResponseHandler.handle(method, path, connection, self).parse
|
230
|
+
response = ResponseHandler.handle(method, path, get_connection_provider.send(method, path, *args))
|
222
231
|
rescue Exception => e
|
223
|
-
raise Error::ServerNotAvailableError.new(self, Response.new(method, path, 503, nil, {}
|
232
|
+
raise Error::ServerNotAvailableError.new(self, Response.new(method, path, 503, nil, {}), e )
|
224
233
|
end
|
225
234
|
|
226
235
|
case response.code
|
@@ -342,6 +351,10 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
342
351
|
request(:post, path, payload, headers)
|
343
352
|
end
|
344
353
|
|
354
|
+
def patch(payload)
|
355
|
+
request(:patch, path, payload, headers)
|
356
|
+
end
|
357
|
+
|
345
358
|
def put(payload)
|
346
359
|
request(:put, path, payload, headers)
|
347
360
|
end
|
@@ -362,6 +375,10 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
362
375
|
request!(:post, path, payload, headers)
|
363
376
|
end
|
364
377
|
|
378
|
+
def patch!(payload)
|
379
|
+
request!(:patch, path, payload, headers)
|
380
|
+
end
|
381
|
+
|
365
382
|
def put!(payload)
|
366
383
|
request!(:put, path, payload, headers)
|
367
384
|
end
|
@@ -378,6 +395,7 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
378
395
|
|
379
396
|
end
|
380
397
|
|
398
|
+
|
381
399
|
#=RequestHistory
|
382
400
|
# Uses RequestBuilder and remind previous requests
|
383
401
|
#
|
@@ -386,7 +404,7 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
386
404
|
# @executor = ::Restfulie::Client::HTTP::RequestHistoryExecutor.new("http://restfulie.com") #this class includes RequestHistory module.
|
387
405
|
# @executor.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #first request
|
388
406
|
# @executor.at('/blogs').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #second request
|
389
|
-
# @executor.request_history!(0) #doing first request
|
407
|
+
# @executor.request_history!(0) #doing first request
|
390
408
|
#
|
391
409
|
module RequestHistory
|
392
410
|
include RequestBuilder
|
@@ -457,29 +475,26 @@ module Restfulie::Client::HTTP #:nodoc:
|
|
457
475
|
end
|
458
476
|
|
459
477
|
#=This class includes RequestBuilder module.
|
460
|
-
class RequestBuilderExecutor
|
478
|
+
class RequestBuilderExecutor < RequestExecutor
|
461
479
|
include RequestBuilder
|
462
480
|
|
463
|
-
# * <tt> host (e.g. 'http://restfulie.com') </tt>
|
464
|
-
# * <tt> default_headers (e.g. {'Cache-control' => 'no-cache'} ) </tt>
|
465
|
-
def initialize(host, default_headers = {})
|
466
|
-
self.host=host
|
467
|
-
self.default_headers=default_headers
|
468
|
-
end
|
469
481
|
def host=(host)
|
470
482
|
super
|
471
483
|
at(self.host.path)
|
472
484
|
end
|
485
|
+
|
473
486
|
def at(path)
|
474
487
|
@path = path
|
475
488
|
self
|
476
489
|
end
|
490
|
+
|
477
491
|
def path
|
478
492
|
@path
|
479
493
|
end
|
494
|
+
|
480
495
|
end
|
481
496
|
|
482
|
-
#=This class inherits
|
497
|
+
#=This class inherits RequestFollowExecutor and include RequestHistory module.
|
483
498
|
class RequestHistoryExecutor < RequestBuilderExecutor
|
484
499
|
include RequestHistory
|
485
500
|
end
|
@@ -1,69 +1,4 @@
|
|
1
1
|
module Restfulie::Client::HTTP#:nodoc:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
def method_missing(method_sym,*args)
|
6
|
-
return super(method_sym, *args) unless simple_extensions
|
7
|
-
|
8
|
-
found = find_extension_entry_for(method_sym)
|
9
|
-
return super(method_sym, *args) if found.empty?
|
10
|
-
result = found.collect do |pair|
|
11
|
-
pair.last.length==1 ? pair.last.first : pair.last
|
12
|
-
end
|
13
|
-
result.length==1 ? result.first : result
|
14
|
-
end
|
15
|
-
|
16
|
-
def respond_to?(method_sym)
|
17
|
-
return super(method_sym) unless simple_extensions
|
18
|
-
|
19
|
-
found = find_extension_entry_for(method_sym)
|
20
|
-
(found.length!=0) || super(method_sym)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
def find_extension_entry_for(method_sym)
|
25
|
-
start = -(method_sym.to_s.length + 1)
|
26
|
-
found = simple_extensions.select do |k, v|
|
27
|
-
method_sym.to_s == k[start..-2]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Offers a way to access Atom entries element's in namespaced extensions.
|
33
|
-
module AtomElementShortcut
|
34
|
-
def method_missing(method_sym,*args)
|
35
|
-
return super(method_sym, *args) unless simple_extensions
|
36
|
-
|
37
|
-
start = -(method_sym.to_s.length + 1)
|
38
|
-
found = simple_extensions.select do |k, v|
|
39
|
-
method_sym.to_s == k[start..-2]
|
40
|
-
end
|
41
|
-
return super(method_sym, *args) if found.empty?
|
42
|
-
result = found.collect do |pair|
|
43
|
-
pair.last.length==1 ? pair.last.first : pair.last
|
44
|
-
end
|
45
|
-
result.length==1 ? result.first : result
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# inject new behavior in rAtom instances to enable easily access to link relationships.
|
50
|
-
::Atom::Feed.instance_eval {
|
51
|
-
include Restfulie::Client::LinkShortcut
|
52
|
-
include AtomElementShortcut
|
53
|
-
}
|
54
|
-
::Atom::Entry.instance_eval {
|
55
|
-
include Restfulie::Client::LinkShortcut
|
56
|
-
include AtomElementShortcut
|
57
|
-
}
|
58
|
-
::Atom::Link.instance_eval {
|
59
|
-
include Restfulie::Client::HTTP::LinkRequestBuilder
|
60
|
-
}
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
class Atom::Link
|
66
|
-
def content_type
|
67
|
-
type
|
68
|
-
end
|
69
|
-
end
|
2
|
+
# inject new behavior in Atom instances to enable easily access to link relationships.
|
3
|
+
::Restfulie::Common::Representation::Atom::Link.instance_eval { include LinkRequestBuilder }
|
4
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Net::HTTP::Patch < Net::HTTP::Get
|
2
|
+
METHOD = "PATCH"
|
3
|
+
end
|
4
|
+
|
5
|
+
# Definition of a patch method in the same way that post works
|
6
|
+
class Net::HTTP
|
7
|
+
def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segment+
|
8
|
+
res = nil
|
9
|
+
request(Patch.new(path, initheader), data) {|r|
|
10
|
+
r.read_body dest, &block
|
11
|
+
res = r
|
12
|
+
}
|
13
|
+
unless @newimpl
|
14
|
+
res.value
|
15
|
+
return res, res.body
|
16
|
+
end
|
17
|
+
res
|
18
|
+
end
|
19
|
+
end
|
@@ -3,11 +3,6 @@ module Restfulie::Client::HTTP#:nodoc:
|
|
3
3
|
#Client errors
|
4
4
|
module Error
|
5
5
|
|
6
|
-
#Generic error class and superclass of all other errors raised by client restfulie
|
7
|
-
class BaseError < StandardError; end
|
8
|
-
|
9
|
-
class TranslationError < BaseError; end
|
10
|
-
|
11
6
|
# Standard error thrown on major client exceptions
|
12
7
|
class RESTError < StandardError
|
13
8
|
|
@@ -20,13 +15,15 @@ module Restfulie::Client::HTTP#:nodoc:
|
|
20
15
|
end
|
21
16
|
|
22
17
|
def to_s
|
23
|
-
"HTTP error #{@response.code} when invoking #{@request.host}
|
18
|
+
"HTTP error #{@response.code} when invoking #{@request.host} via #{@response.method}. " +
|
24
19
|
((@response.body.blank?) ? "No additional data was sent." : "The complete response was:\n" + @response.body)
|
25
20
|
rescue
|
26
21
|
super
|
27
22
|
end
|
28
23
|
|
29
24
|
end
|
25
|
+
|
26
|
+
class AutoFollowWithoutLocationError < RESTError; end
|
30
27
|
|
31
28
|
#Represents the HTTP code 503
|
32
29
|
class ServerNotAvailableError < RESTError
|
@@ -3,48 +3,30 @@ module Restfulie::Client::HTTP
|
|
3
3
|
|
4
4
|
module ResponseHolder
|
5
5
|
attr_accessor :response
|
6
|
-
|
7
|
-
def respond_to?(symbol)
|
8
|
-
super(symbol) || (super(:links) && respond_to_rel?(symbol.to_s))
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
# whether this response contains specific relations
|
13
|
-
def respond_to_rel?(rel)
|
14
|
-
links.any? { |link| link.rel==rel }
|
15
|
-
end
|
16
|
-
|
17
6
|
end
|
18
7
|
|
19
8
|
module RequestMarshaller
|
20
|
-
include ::Restfulie::Client::HTTP::
|
9
|
+
include ::Restfulie::Client::HTTP::RequestHistory
|
21
10
|
|
22
|
-
# accepts a series of media types by default
|
23
|
-
def initialize
|
24
|
-
end
|
25
|
-
|
26
11
|
@@representations = {
|
27
|
-
'application/atom+xml' => ::Restfulie::Common::
|
12
|
+
'application/atom+xml' => ::Restfulie::Common::Converter::Atom
|
28
13
|
}
|
29
14
|
def self.register_representation(media_type,representation)
|
30
15
|
@@representations[media_type] = representation
|
31
16
|
end
|
32
17
|
|
33
|
-
RequestMarshaller.register_representation('application/xml', ::Restfulie::Common::
|
34
|
-
RequestMarshaller.register_representation('text/xml', ::Restfulie::Common::
|
18
|
+
RequestMarshaller.register_representation('application/xml', ::Restfulie::Common::Converter::Xml)
|
19
|
+
RequestMarshaller.register_representation('text/xml', ::Restfulie::Common::Converter::Xml)
|
35
20
|
RequestMarshaller.register_representation('application/json', ::Restfulie::Common::Representation::Json)
|
36
21
|
|
37
22
|
def self.content_type_for(media_type)
|
38
23
|
return nil unless media_type
|
39
24
|
content_type = media_type.split(';')[0] # [/(.*?);/, 1]
|
40
|
-
|
41
|
-
type ? type.new : nil
|
25
|
+
@@representations[content_type]
|
42
26
|
end
|
43
27
|
|
44
28
|
def accepts(media_types)
|
45
|
-
@acceptable_mediatypes = media_types
|
46
29
|
@default_representation = @@representations[media_types]
|
47
|
-
raise "Undefined representation for #{media_types}" unless @default_representation
|
48
30
|
super
|
49
31
|
end
|
50
32
|
|
@@ -53,16 +35,26 @@ module Restfulie::Client::HTTP
|
|
53
35
|
self
|
54
36
|
end
|
55
37
|
|
56
|
-
|
57
|
-
|
58
|
-
|
38
|
+
def post(payload, options = { :recipe => nil })
|
39
|
+
request(:post, path, payload, options.merge(headers))
|
40
|
+
end
|
41
|
+
|
42
|
+
def post!(payload, options = { :recipe => nil })
|
43
|
+
request!(:post, path, payload, options.merge(headers))
|
44
|
+
end
|
45
|
+
|
46
|
+
#Executes super if its a raw request, returning the content itself.
|
47
|
+
#otherwise tries to parse the content with a mediatype handler or returns the response itself.
|
48
|
+
def request!(method, path, *args)
|
59
49
|
if has_payload?(method, path, *args)
|
50
|
+
recipe = get_recipe(*args)
|
51
|
+
|
60
52
|
payload = get_payload(method, path, *args)
|
61
53
|
rel = self.respond_to?(:rel) ? self.rel : ""
|
62
54
|
type = headers['Content-Type']
|
63
55
|
raise Restfulie::Common::Error::RestfulieError, "Missing content type related to the data to be submitted" unless type
|
64
56
|
marshaller = RequestMarshaller.content_type_for(type)
|
65
|
-
payload = marshaller.marshal(payload, rel)
|
57
|
+
payload = marshaller.marshal(payload, { :rel => rel, :recipe => recipe })
|
66
58
|
args = set_marshalled_payload(method, path, payload, *args)
|
67
59
|
args = add_representation_headers(method, path, marshaller, *args)
|
68
60
|
end
|
@@ -78,7 +70,6 @@ module Restfulie::Client::HTTP
|
|
78
70
|
|
79
71
|
private
|
80
72
|
|
81
|
-
|
82
73
|
# parses the http response.
|
83
74
|
# first checks if its a 201, redirecting to the resource location.
|
84
75
|
# otherwise check if its a raw request, returning the content itself.
|
@@ -97,12 +88,21 @@ module Restfulie::Client::HTTP
|
|
97
88
|
unmarshalled.response = response
|
98
89
|
unmarshalled
|
99
90
|
else
|
91
|
+
response.extend(ResponseHolder)
|
92
|
+
response.response = response
|
100
93
|
response
|
101
94
|
end
|
102
95
|
end
|
103
|
-
|
96
|
+
|
97
|
+
def get_recipe(*args)
|
98
|
+
headers_and_recipe = args.extract_options!
|
99
|
+
recipe = headers_and_recipe.delete(:recipe)
|
100
|
+
args << headers_and_recipe
|
101
|
+
recipe
|
102
|
+
end
|
103
|
+
|
104
104
|
def has_payload?(method, path, *args)
|
105
|
-
[:put,:post].include?(method)
|
105
|
+
[:put,:post,:patch].include?(method)
|
106
106
|
end
|
107
107
|
|
108
108
|
def get_payload(method, path, *args)
|
@@ -126,34 +126,20 @@ module Restfulie::Client::HTTP
|
|
126
126
|
|
127
127
|
end
|
128
128
|
|
129
|
-
#
|
129
|
+
# NOTE: When including this module remember to override the type method to return
|
130
|
+
# a valid content type as a string.
|
130
131
|
module LinkRequestBuilder
|
131
|
-
include
|
132
|
+
include RequestMarshaller
|
132
133
|
def path#:nodoc:
|
133
134
|
at(href)
|
134
|
-
as(
|
135
|
+
as(type) if type
|
135
136
|
super
|
136
137
|
end
|
137
138
|
end
|
138
139
|
|
139
140
|
#=This class includes RequestBuilder module.
|
140
|
-
class RequestMarshallerExecutor
|
141
|
+
class RequestMarshallerExecutor < RequestHistoryExecutor
|
141
142
|
include RequestMarshaller
|
142
|
-
|
143
|
-
# * <tt> host (e.g. 'http://restfulie.com') </tt>
|
144
|
-
# * <tt> default_headers (e.g. {'Cache-control' => 'no-cache'} ) </tt>
|
145
|
-
def initialize(host, default_headers = {})
|
146
|
-
self.host=host
|
147
|
-
self.default_headers=default_headers
|
148
|
-
end
|
149
|
-
|
150
|
-
def at(path)
|
151
|
-
@path = path
|
152
|
-
self
|
153
|
-
end
|
154
|
-
def path
|
155
|
-
@path
|
156
|
-
end
|
157
143
|
end
|
158
144
|
|
159
145
|
end
|