restfulie 0.9.3 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +2 -2
- data/README.textile +4 -2
- data/Rakefile +12 -13
- data/lib/restfulie/client/base.rb +9 -2
- data/lib/restfulie/client/cache/basic.rb +6 -5
- data/lib/restfulie/client/cache/http_ext.rb +10 -8
- data/lib/restfulie/client/cache/restrictions.rb +1 -6
- data/lib/restfulie/client/dsl.rb +66 -0
- data/lib/restfulie/client/entry_point.rb +34 -9
- data/lib/restfulie/client/ext/atom_ext.rb +4 -2
- data/lib/restfulie/client/ext/json_ext.rb +5 -1
- data/lib/restfulie/client/feature/base.rb +75 -0
- data/lib/restfulie/client/feature/base_request.rb +35 -0
- data/lib/restfulie/client/feature/cache.rb +16 -0
- data/lib/restfulie/client/feature/enhance_response.rb +12 -0
- data/lib/restfulie/client/feature/follow_request.rb +41 -0
- data/lib/restfulie/client/feature/history.rb +26 -0
- data/lib/restfulie/client/feature/history_request.rb +19 -0
- data/lib/restfulie/client/feature/open_search/pattern_matcher.rb +25 -0
- data/lib/restfulie/client/feature/open_search.rb +21 -0
- data/lib/restfulie/client/feature/serialize_body.rb +32 -0
- data/lib/restfulie/client/feature/setup_header.rb +22 -0
- data/lib/restfulie/client/feature/throw_error.rb +41 -0
- data/lib/restfulie/client/feature/verb.rb +119 -0
- data/lib/restfulie/client/feature.rb +5 -0
- data/lib/restfulie/client/http/response_holder.rb +26 -6
- data/lib/restfulie/client/http.rb +1 -21
- data/lib/restfulie/client/master_delegator.rb +31 -0
- data/lib/restfulie/client/mikyung/core.rb +5 -4
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +1 -1
- data/lib/restfulie/client/mikyung.rb +1 -8
- data/lib/restfulie/client.rb +3 -1
- data/lib/restfulie/common/converter/atom/base.rb +2 -0
- data/lib/restfulie/common/converter/form_url_encoded.rb +16 -0
- data/lib/restfulie/common/converter/json/base.rb +5 -2
- data/lib/restfulie/common/converter/open_search/descriptor.rb +32 -0
- data/lib/restfulie/common/converter/open_search.rb +16 -0
- data/lib/restfulie/common/converter/xml/base.rb +3 -1
- data/lib/restfulie/common/converter/xml/builder.rb +3 -2
- data/lib/restfulie/common/converter/xml/helpers.rb +4 -4
- data/lib/restfulie/common/converter/xml/link.rb +5 -0
- data/lib/restfulie/common/converter/xml/links.rb +1 -5
- data/lib/restfulie/common/converter.rb +25 -4
- data/lib/restfulie/common/core_ext/hash.rb +6 -0
- data/lib/restfulie/common/links.rb +9 -0
- data/lib/restfulie/common/representation/atom/base.rb +34 -33
- data/lib/restfulie/common/representation/atom/xml.rb +5 -10
- data/lib/restfulie/common/representation/generic.rb +0 -12
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +2 -0
- data/lib/restfulie/common/representation.rb +2 -9
- data/lib/restfulie/common.rb +2 -1
- data/lib/restfulie/server/action_controller/trait/cacheable.rb +81 -0
- data/lib/restfulie/server/action_controller/trait/created.rb +17 -0
- data/lib/restfulie/server/action_controller/trait/save_prior_to_create.rb +13 -0
- data/lib/restfulie/server/action_controller/trait.rb +9 -0
- data/lib/restfulie/server/action_controller.rb +1 -5
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +1 -1
- data/lib/restfulie/server.rb +6 -0
- data/lib/restfulie/version.rb +4 -4
- data/lib/restfulie.rb +21 -3
- metadata +37 -26
- data/lib/restfulie/client/ext/xml_ext.rb +0 -4
- data/lib/restfulie/client/http/link_request_builder.rb +0 -16
- data/lib/restfulie/client/http/request_adapter.rb +0 -213
- data/lib/restfulie/client/http/request_builder.rb +0 -114
- data/lib/restfulie/client/http/request_builder_executor.rb +0 -24
- data/lib/restfulie/client/http/request_executor.rb +0 -17
- data/lib/restfulie/client/http/request_follow.rb +0 -42
- data/lib/restfulie/client/http/request_follow_executor.rb +0 -10
- data/lib/restfulie/client/http/request_history.rb +0 -71
- data/lib/restfulie/client/http/request_history_executor.rb +0 -10
- data/lib/restfulie/client/http/request_marshaller.rb +0 -129
- data/lib/restfulie/client/http/request_marshaller_executor.rb +0 -10
- data/lib/restfulie/client/http/response.rb +0 -23
- data/lib/restfulie/client/http/response_handler.rb +0 -67
- data/lib/restfulie/server/action_controller/cacheable_responder.rb +0 -77
- data/lib/restfulie/server/action_controller/created_responder.rb +0 -19
@@ -1,213 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
# Request Adapter provides a minimal interface to exchange information between server over HTTP protocol through simple adapters.
|
5
|
-
#
|
6
|
-
# All the concrete adapters follow the interface laid down in this module.
|
7
|
-
# Default connection provider is net/http
|
8
|
-
#
|
9
|
-
#==Example
|
10
|
-
#
|
11
|
-
# @re = ::Restfulie::Client::HTTP::RequestExecutor.new('http://restfulie.com') #this class includes RequestAdapter module.
|
12
|
-
# puts @re.as('application/atom+xml').get!('/posts').title #=> 'Hello World!'
|
13
|
-
#
|
14
|
-
module RequestAdapter
|
15
|
-
attr_reader :host
|
16
|
-
attr_accessor :cookies
|
17
|
-
attr_writer :default_headers
|
18
|
-
|
19
|
-
def host=(host)
|
20
|
-
if host.is_a?(::URI)
|
21
|
-
@host = host
|
22
|
-
else
|
23
|
-
@host = ::URI.parse(host)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def default_headers
|
28
|
-
@default_headers ||= {}
|
29
|
-
end
|
30
|
-
|
31
|
-
# GET HTTP verb without {Error}
|
32
|
-
# * <tt>path: '/posts'</tt>
|
33
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
34
|
-
def get(path, *args)
|
35
|
-
request(:get, path, *args)
|
36
|
-
end
|
37
|
-
|
38
|
-
# HEAD HTTP verb without {Error}
|
39
|
-
# * <tt>path: '/posts'</tt>
|
40
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
41
|
-
def head(path, *args)
|
42
|
-
request(:head, path, *args)
|
43
|
-
end
|
44
|
-
|
45
|
-
# POST HTTP verb without {Error}
|
46
|
-
# * <tt>path: '/posts'</tt>
|
47
|
-
# * <tt>payload: 'some text'</tt>
|
48
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
49
|
-
def post(path, payload, *args)
|
50
|
-
request(:post, path, payload, *args)
|
51
|
-
end
|
52
|
-
|
53
|
-
# PATCH HTTP verb without {Error}
|
54
|
-
# * <tt>path: '/posts'</tt>
|
55
|
-
# * <tt>payload: 'some text'</tt>
|
56
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
57
|
-
def patch(path, payload, *args)
|
58
|
-
request(:patch, path, payload, *args)
|
59
|
-
end
|
60
|
-
|
61
|
-
# PUT HTTP verb without {Error}
|
62
|
-
# * <tt>path: '/posts'</tt>
|
63
|
-
# * <tt>payload: 'some text'</tt>
|
64
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
65
|
-
def put(path, payload, *args)
|
66
|
-
request(:put, path, payload, *args)
|
67
|
-
end
|
68
|
-
|
69
|
-
# DELETE HTTP verb without {Error}
|
70
|
-
# * <tt>path: '/posts'</tt>
|
71
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
72
|
-
def delete(path, *args)
|
73
|
-
request(:delete, path, *args)
|
74
|
-
end
|
75
|
-
|
76
|
-
# GET HTTP verb {Error}
|
77
|
-
# * <tt>path: '/posts'</tt>
|
78
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
79
|
-
def get!(path, *args)
|
80
|
-
request!(:get, path, *args)
|
81
|
-
end
|
82
|
-
|
83
|
-
# HEAD HTTP verb {Error}
|
84
|
-
# * <tt>path: '/posts'</tt>
|
85
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
86
|
-
def head!(path, *args)
|
87
|
-
request!(:head, path, *args)
|
88
|
-
end
|
89
|
-
|
90
|
-
# POST HTTP verb {Error}
|
91
|
-
# * <tt>path: '/posts'</tt>
|
92
|
-
# * <tt>payload: 'some text'</tt>
|
93
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
94
|
-
def post!(path, payload, *args)
|
95
|
-
request!(:post, path, payload, *args)
|
96
|
-
end
|
97
|
-
|
98
|
-
# PATCH HTTP verb {Error}
|
99
|
-
# * <tt>path: '/posts'</tt>
|
100
|
-
# * <tt>payload: 'some text'</tt>
|
101
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
102
|
-
def patch!(path, payload, *args)
|
103
|
-
request!(:patch, path, payload, *args)
|
104
|
-
end
|
105
|
-
|
106
|
-
# PUT HTTP verb {Error}
|
107
|
-
# * <tt>path: '/posts'</tt>
|
108
|
-
# * <tt>payload: 'some text'</tt>
|
109
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
110
|
-
def put!(path, payload, *args)
|
111
|
-
request!(:put, path, payload, *args)
|
112
|
-
end
|
113
|
-
|
114
|
-
# DELETE HTTP verb {Error}
|
115
|
-
# * <tt>path: '/posts'</tt>
|
116
|
-
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
117
|
-
def delete!(path, *args)
|
118
|
-
request!(:delete, path, *args)
|
119
|
-
end
|
120
|
-
|
121
|
-
# Executes a request against your server and return a response instance without {Error}
|
122
|
-
# * <tt>method: :get,:post,:delete,:head,:put</tt>
|
123
|
-
# * <tt>path: '/posts'</tt>
|
124
|
-
# * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
125
|
-
def request(method, path, *args)
|
126
|
-
request!(method, path, *args)
|
127
|
-
rescue Error::RESTError => se
|
128
|
-
[[@host, path], nil, se.response]
|
129
|
-
end
|
130
|
-
|
131
|
-
# Executes a request against your server and return a response instance.
|
132
|
-
# * <tt>method: :get,:post,:delete,:head,:put</tt>
|
133
|
-
# * <tt>path: '/posts'</tt>
|
134
|
-
# * <tt>args: payload: 'some text' and/or headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
135
|
-
def request!(method, path, *args)
|
136
|
-
headers = default_headers.merge(args.extract_options!)
|
137
|
-
unless @host.user.blank? && @host.password.blank?
|
138
|
-
headers["Authorization"] = "Basic " + ["#{@host.user}:#{@host.password}"].pack("m").delete("\r\n")
|
139
|
-
end
|
140
|
-
headers['cookie'] = @cookies if @cookies
|
141
|
-
args << headers
|
142
|
-
|
143
|
-
::Restfulie::Common::Logger.logger.info(request_to_s(method, path, *args)) if ::Restfulie::Common::Logger.logger
|
144
|
-
begin
|
145
|
-
http_request = get_connection_provider
|
146
|
-
response = Restfulie::Client.cache_provider.get([@host, path], http_request, method)
|
147
|
-
return [[@host, path], http_request, response] if response
|
148
|
-
response = ResponseHandler.handle(method, path, http_request.send(method, path, *args))
|
149
|
-
rescue Exception => e
|
150
|
-
Restfulie::Common::Logger.logger.error(e)
|
151
|
-
raise Error::ServerNotAvailableError.new(self, Response.new(method, path, 503, nil, {}), e )
|
152
|
-
end
|
153
|
-
|
154
|
-
case response.code
|
155
|
-
when 100..299
|
156
|
-
[[@host, path], http_request, response]
|
157
|
-
when 300..399
|
158
|
-
raise Error::Redirection.new(self, response)
|
159
|
-
when 400
|
160
|
-
raise Error::BadRequest.new(self, response)
|
161
|
-
when 401
|
162
|
-
raise Error::Unauthorized.new(self, response)
|
163
|
-
when 403
|
164
|
-
raise Error::Forbidden.new(self, response)
|
165
|
-
when 404
|
166
|
-
raise Error::NotFound.new(self, response)
|
167
|
-
when 405
|
168
|
-
raise Error::MethodNotAllowed.new(self, response)
|
169
|
-
when 407
|
170
|
-
raise Error::ProxyAuthenticationRequired.new(self, response)
|
171
|
-
when 409
|
172
|
-
raise Error::Conflict.new(self, response)
|
173
|
-
when 410
|
174
|
-
raise Error::Gone.new(self, response)
|
175
|
-
when 412
|
176
|
-
raise Error::PreconditionFailed.new(self, response)
|
177
|
-
when 402, 406, 408, 411, 413..499
|
178
|
-
raise Error::ClientError.new(self, response)
|
179
|
-
when 501
|
180
|
-
raise Error::NotImplemented.new(self, response)
|
181
|
-
when 500, 502..599
|
182
|
-
raise Error::ServerError.new(self, response)
|
183
|
-
else
|
184
|
-
raise Error::UnknownError.new(self, response)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
private
|
189
|
-
|
190
|
-
def get_connection_provider
|
191
|
-
@connection ||= ::Net::HTTP.new(@host.host, @host.port)
|
192
|
-
end
|
193
|
-
|
194
|
-
protected
|
195
|
-
|
196
|
-
def request_to_s(method, path, *args)
|
197
|
-
result = ["#{method.to_s.upcase} #{path}"]
|
198
|
-
|
199
|
-
arguments = args.dup
|
200
|
-
headers = arguments.extract_options!
|
201
|
-
|
202
|
-
if [:post, :put].include?(method)
|
203
|
-
body = arguments.shift
|
204
|
-
end
|
205
|
-
|
206
|
-
result << headers.collect { |key, value| "#{key}: #{value}" }.join("\n")
|
207
|
-
|
208
|
-
(result + [body ? (body.inspect + "\n") : nil]).compact.join("\n") << "\n"
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
@@ -1,114 +0,0 @@
|
|
1
|
-
require 'uri'
|
2
|
-
|
3
|
-
module Restfulie
|
4
|
-
module Client
|
5
|
-
module HTTP #:nodoc:
|
6
|
-
# ==== RequestBuilder
|
7
|
-
# Uses RequestAdapater to create a HTTP Request DSL
|
8
|
-
#
|
9
|
-
# ==== Example:
|
10
|
-
#
|
11
|
-
# @builder = ::Restfulie::Client::HTTP::RequestBuilderExecutor.new("http://restfulie.com") #this class includes RequestBuilder module.
|
12
|
-
# @builder.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200
|
13
|
-
#
|
14
|
-
module RequestBuilder
|
15
|
-
include RequestAdapter
|
16
|
-
|
17
|
-
#Set host
|
18
|
-
def at(url)
|
19
|
-
self.host = url
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
#Set Content-Type and Accept headers
|
24
|
-
def as(content_type)
|
25
|
-
headers['Content-Type'] = content_type
|
26
|
-
accepts(content_type)
|
27
|
-
end
|
28
|
-
|
29
|
-
#Set Accept headers
|
30
|
-
def accepts(content_type)
|
31
|
-
headers['Accept'] = content_type
|
32
|
-
self
|
33
|
-
end
|
34
|
-
|
35
|
-
# Merge internal header
|
36
|
-
#
|
37
|
-
# * <tt>headers (e.g. {'Cache-control' => 'no-cache'})</tt>
|
38
|
-
#
|
39
|
-
def with(headers)
|
40
|
-
self.headers.merge!(headers)
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
def headers
|
45
|
-
@headers ||= {}
|
46
|
-
end
|
47
|
-
|
48
|
-
# Path (e.g. http://restfulie.com/posts => /posts)
|
49
|
-
def path
|
50
|
-
host.path
|
51
|
-
end
|
52
|
-
|
53
|
-
def get(params = {})
|
54
|
-
request(:get, add_querystring(path, params), headers)
|
55
|
-
end
|
56
|
-
|
57
|
-
def head
|
58
|
-
request(:head, path, headers)
|
59
|
-
end
|
60
|
-
|
61
|
-
def post(payload)
|
62
|
-
request(:post, path, payload, headers)
|
63
|
-
end
|
64
|
-
|
65
|
-
def patch(payload)
|
66
|
-
request(:patch, path, payload, headers)
|
67
|
-
end
|
68
|
-
|
69
|
-
def put(payload)
|
70
|
-
request(:put, path, payload, headers)
|
71
|
-
end
|
72
|
-
|
73
|
-
def delete
|
74
|
-
request(:delete, path, headers)
|
75
|
-
end
|
76
|
-
|
77
|
-
def get!(params = {})
|
78
|
-
request!(:get, add_querystring(path, params), headers)
|
79
|
-
end
|
80
|
-
|
81
|
-
def head!
|
82
|
-
request!(:head, path, headers)
|
83
|
-
end
|
84
|
-
|
85
|
-
def post!(payload)
|
86
|
-
request!(:post, path, payload, headers)
|
87
|
-
end
|
88
|
-
|
89
|
-
def patch!(payload)
|
90
|
-
request!(:patch, path, payload, headers)
|
91
|
-
end
|
92
|
-
|
93
|
-
def put!(payload)
|
94
|
-
request!(:put, path, payload, headers)
|
95
|
-
end
|
96
|
-
|
97
|
-
def delete!
|
98
|
-
request!(:delete, path, headers)
|
99
|
-
end
|
100
|
-
|
101
|
-
protected
|
102
|
-
|
103
|
-
def add_querystring(path, params)
|
104
|
-
params = params.map { |param, value| "#{param}=#{value}"}.join("&")
|
105
|
-
params.blank? ? path : URI.escape("#{path}?#{params}")
|
106
|
-
end
|
107
|
-
|
108
|
-
def headers=(h)
|
109
|
-
@headers = h
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
#=This class includes RequestBuilder module.
|
5
|
-
class RequestBuilderExecutor < RequestExecutor
|
6
|
-
include RequestBuilder
|
7
|
-
|
8
|
-
def host=(host)
|
9
|
-
super
|
10
|
-
at(self.host.path)
|
11
|
-
end
|
12
|
-
|
13
|
-
def at(path)
|
14
|
-
@path = path
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
def path
|
19
|
-
@path
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
#=This class includes RequestAdapter module.
|
5
|
-
class RequestExecutor
|
6
|
-
include RequestAdapter
|
7
|
-
|
8
|
-
# * <tt> host (e.g. 'http://restfulie.com') </tt>
|
9
|
-
# * <tt> default_headers (e.g. {'Cache-control' => 'no-cache'} ) </tt>
|
10
|
-
def initialize(host, default_headers = {})
|
11
|
-
self.host=host
|
12
|
-
self.default_headers=default_headers
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
# ==== RequestFollow follow new location of a document usually with response codes 201,301,302,303 and 307. You can also configure other codes.
|
5
|
-
#
|
6
|
-
# ==== Example:
|
7
|
-
# @executor = ::Restfulie::Client::HTTP::RequestFollowExecutor.new("http://restfulie.com") #this class includes RequestFollow module.
|
8
|
-
# @executor.at('/custom/songs').accepts('application/atom+xml').follow(201).post!("custom").code
|
9
|
-
module RequestFollow
|
10
|
-
include RequestBuilder
|
11
|
-
|
12
|
-
def follow(code = nil)
|
13
|
-
@follow ||= true # turn on follow redirection
|
14
|
-
follow_codes << code unless code.nil? or follow_codes.include?(code)
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
def request!(method, path, *args)#:nodoc:
|
19
|
-
begin
|
20
|
-
response = super
|
21
|
-
rescue Error::Redirection => e
|
22
|
-
raise e unless @follow # normal behavior for bang methods is to raise the exception
|
23
|
-
response = e.response
|
24
|
-
if follow_codes.include?(response.code)
|
25
|
-
location = response.headers['location'] || response.headers['Location']
|
26
|
-
raise Error::AutoFollowWithoutLocationError.new(self, response) unless location
|
27
|
-
self.host = location
|
28
|
-
response = super(:get, location, headers)
|
29
|
-
end
|
30
|
-
response
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def follow_codes
|
37
|
-
@follow_codes ||= [201,301,302,303,307]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
# ==== RequestHistory
|
5
|
-
# Uses RequestBuilder and remind previous requests
|
6
|
-
#
|
7
|
-
# ==== Example:
|
8
|
-
#
|
9
|
-
# @executor = ::Restfulie::Client::HTTP::RequestHistoryExecutor.new("http://restfulie.com") #this class includes RequestHistory module.
|
10
|
-
# @executor.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #first request
|
11
|
-
# @executor.at('/blogs').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200 #second request
|
12
|
-
# @executor.request_history!(0) #doing first request
|
13
|
-
#
|
14
|
-
module RequestHistory
|
15
|
-
include RequestBuilder
|
16
|
-
|
17
|
-
def snapshots
|
18
|
-
@snapshots ||= []
|
19
|
-
end
|
20
|
-
|
21
|
-
def max_to_remind
|
22
|
-
10
|
23
|
-
end
|
24
|
-
|
25
|
-
def request!(method=nil, path=nil, *args)#:nodoc:
|
26
|
-
if method == nil || path == nil
|
27
|
-
raise 'History not selected' unless @snapshot
|
28
|
-
super( @snapshot[:method], @snapshot[:path], *@snapshot[:args] )
|
29
|
-
else
|
30
|
-
@snapshot = make_snapshot(method, path, *args)
|
31
|
-
unless snapshots.include?(@snapshot)
|
32
|
-
snapshots.shift if snapshots.size >= max_to_remind
|
33
|
-
snapshots << @snapshot
|
34
|
-
end
|
35
|
-
super
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def request(method=nil, path=nil, *args)#:nodoc:
|
40
|
-
request!(method, path, *args)
|
41
|
-
rescue Error::RESTError => se
|
42
|
-
[[@host, path], nil, se.response]
|
43
|
-
end
|
44
|
-
|
45
|
-
def history(number)
|
46
|
-
@snapshot = snapshots[number]
|
47
|
-
raise "Undefined snapshot for #{number}" unless @snapshot
|
48
|
-
self.host = @snapshot[:host]
|
49
|
-
self.cookies = @snapshot[:cookies]
|
50
|
-
self.headers = @snapshot[:headers]
|
51
|
-
self.default_headers = @snapshot[:default_headers]
|
52
|
-
at(@snapshot[:path])
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def make_snapshot(method, path, *args)
|
58
|
-
arguments = args.dup
|
59
|
-
cutom_headers = arguments.extract_options!
|
60
|
-
{ :host => self.host.dup,
|
61
|
-
:default_headers => self.default_headers.dup,
|
62
|
-
:headers => self.headers.dup,
|
63
|
-
:cookies => self.cookies,
|
64
|
-
:method => method,
|
65
|
-
:path => path,
|
66
|
-
:args => arguments << self.headers.merge(cutom_headers) }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,129 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP
|
4
|
-
module RequestMarshaller
|
5
|
-
include RequestHistory
|
6
|
-
|
7
|
-
@@representations = {
|
8
|
-
'application/atom+xml' => ::Restfulie::Common::Converter::Atom,
|
9
|
-
'application/xml' => ::Restfulie::Common::Converter::Xml,
|
10
|
-
'text/xml' => ::Restfulie::Common::Converter::Xml,
|
11
|
-
'application/json' => ::Restfulie::Common::Converter::Json
|
12
|
-
}
|
13
|
-
|
14
|
-
def self.register_representation(media_type,representation)
|
15
|
-
@@representations[media_type] = representation
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.content_type_for(media_type)
|
19
|
-
return nil unless media_type
|
20
|
-
content_type = media_type.split(';')[0] # [/(.*?);/, 1]
|
21
|
-
@@representations[content_type]
|
22
|
-
end
|
23
|
-
|
24
|
-
def accepts(media_types)
|
25
|
-
@default_representation = @@representations[media_types]
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
|
-
def raw
|
30
|
-
@raw = true
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
def post(payload, options = { :recipe => nil })
|
35
|
-
request(:post, path, payload, options.merge(headers))
|
36
|
-
end
|
37
|
-
|
38
|
-
def post!(payload, options = { :recipe => nil })
|
39
|
-
request!(:post, path, payload, options.merge(headers))
|
40
|
-
end
|
41
|
-
|
42
|
-
# Executes super if its a raw request, returning the content itself.
|
43
|
-
# otherwise tries to parse the content with a mediatype handler or returns the response itself.
|
44
|
-
def request!(method, path, *args)
|
45
|
-
if has_payload?(method, path, *args)
|
46
|
-
recipe = get_recipe(*args)
|
47
|
-
|
48
|
-
payload = get_payload(method, path, *args)
|
49
|
-
rel = self.respond_to?(:rel) ? self.rel : ""
|
50
|
-
type = headers['Content-Type']
|
51
|
-
raise Restfulie::Common::Error::RestfulieError, "Missing content type related to the data to be submitted" unless type
|
52
|
-
marshaller = RequestMarshaller.content_type_for(type)
|
53
|
-
payload = marshaller.marshal(payload, { :rel => rel, :recipe => recipe }) unless payload.nil? || (payload.kind_of?(String) && payload.empty?)
|
54
|
-
args = set_marshalled_payload(method, path, payload, *args)
|
55
|
-
args = add_representation_headers(method, path, marshaller, *args)
|
56
|
-
end
|
57
|
-
|
58
|
-
if @acceptable_mediatypes
|
59
|
-
unmarshaller = RequestMarshaller.content_type_for(@acceptable_mediatypes)
|
60
|
-
args = add_representation_headers(method, path, unmarshaller, *args)
|
61
|
-
end
|
62
|
-
|
63
|
-
key, req, response = super(method, path, *args)
|
64
|
-
Restfulie::Client.cache_provider.put(key, req, response)
|
65
|
-
|
66
|
-
parse_response(response)
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
# parses the http response.
|
72
|
-
# first checks if its a 201, redirecting to the resource location.
|
73
|
-
# otherwise check if its a raw request, returning the content itself.
|
74
|
-
# finally, tries to parse the content with a mediatype handler or returns the response itself.
|
75
|
-
def parse_response(response)
|
76
|
-
if response.code == 201
|
77
|
-
request = Restfulie.at(response.headers['location'])
|
78
|
-
request.accepts(@acceptable_mediatypes) if @acceptable_mediatypes
|
79
|
-
request.get!
|
80
|
-
elsif @raw
|
81
|
-
response
|
82
|
-
elsif !response.body.empty?
|
83
|
-
representation = RequestMarshaller.content_type_for(response.headers['content-type']) || Restfulie::Common::Representation::Generic.new
|
84
|
-
representation.unmarshal(response.body).tap do |u|
|
85
|
-
u.extend(ResponseHolder)
|
86
|
-
u.response = response
|
87
|
-
end
|
88
|
-
else
|
89
|
-
response.tap do |resp|
|
90
|
-
resp.extend(ResponseHolder)
|
91
|
-
resp.response = response
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def get_recipe(*args)
|
97
|
-
headers_and_recipe = args.extract_options!
|
98
|
-
recipe = headers_and_recipe.delete(:recipe)
|
99
|
-
args << headers_and_recipe
|
100
|
-
recipe
|
101
|
-
end
|
102
|
-
|
103
|
-
def has_payload?(method, path, *args)
|
104
|
-
[:put,:post,:patch].include?(method)
|
105
|
-
end
|
106
|
-
|
107
|
-
def get_payload(method, path, *args)
|
108
|
-
args.extract_options! #remove header
|
109
|
-
args.shift #payload
|
110
|
-
end
|
111
|
-
|
112
|
-
def set_marshalled_payload(method, path, payload, *args)
|
113
|
-
headers = args.extract_options!
|
114
|
-
args.tap do |a|
|
115
|
-
a.shift #old payload
|
116
|
-
a << payload << headers
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def add_representation_headers(method, path, representation, *args)
|
121
|
-
headers = args.extract_options!
|
122
|
-
headers = headers.merge(representation.headers[method] || {})
|
123
|
-
args << headers
|
124
|
-
args
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Client
|
3
|
-
module HTTP #:nodoc:
|
4
|
-
#=Response
|
5
|
-
# Default response class
|
6
|
-
class Response
|
7
|
-
attr_reader :method
|
8
|
-
attr_reader :path
|
9
|
-
attr_reader :code
|
10
|
-
attr_reader :body
|
11
|
-
attr_reader :headers
|
12
|
-
|
13
|
-
def initialize(method, path, code, body, headers)
|
14
|
-
@method = method
|
15
|
-
@path = path
|
16
|
-
@code = code
|
17
|
-
@body = body
|
18
|
-
@headers = headers
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|