restfulie 0.8.0 → 0.8.1

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.
Files changed (102) hide show
  1. data/Gemfile +10 -5
  2. data/Rakefile +5 -2
  3. data/lib/restfulie.rb +10 -5
  4. data/lib/restfulie/client.rb +13 -9
  5. data/lib/restfulie/client/base.rb +24 -65
  6. data/lib/restfulie/client/configuration.rb +62 -64
  7. data/lib/restfulie/client/entry_point.rb +36 -0
  8. data/lib/restfulie/client/ext/atom_ext.rb +12 -0
  9. data/lib/restfulie/client/ext/http_ext.rb +22 -0
  10. data/lib/restfulie/client/ext/json_ext.rb +12 -0
  11. data/lib/restfulie/client/ext/xml_ext.rb +4 -0
  12. data/lib/restfulie/client/http.rb +25 -13
  13. data/lib/restfulie/client/http/cache.rb +22 -22
  14. data/lib/restfulie/client/http/error.rb +70 -70
  15. data/lib/restfulie/client/http/link_request_builder.rb +15 -0
  16. data/lib/restfulie/client/http/request_adapter.rb +209 -0
  17. data/lib/restfulie/client/http/request_builder.rb +107 -0
  18. data/lib/restfulie/client/http/request_builder_executor.rb +24 -0
  19. data/lib/restfulie/client/http/request_executor.rb +17 -0
  20. data/lib/restfulie/client/http/request_follow.rb +42 -0
  21. data/lib/restfulie/client/http/request_follow_executor.rb +10 -0
  22. data/lib/restfulie/client/http/request_history.rb +69 -0
  23. data/lib/restfulie/client/http/request_history_executor.rb +10 -0
  24. data/lib/restfulie/client/http/request_marshaller.rb +127 -0
  25. data/lib/restfulie/client/http/request_marshaller_executor.rb +10 -0
  26. data/lib/restfulie/client/http/response.rb +23 -0
  27. data/lib/restfulie/client/http/response_handler.rb +67 -0
  28. data/lib/restfulie/client/http/response_holder.rb +9 -0
  29. data/lib/restfulie/client/mikyung.rb +17 -14
  30. data/lib/restfulie/client/mikyung/concatenator.rb +15 -12
  31. data/lib/restfulie/client/mikyung/core.rb +65 -39
  32. data/lib/restfulie/client/mikyung/languages.rb +8 -26
  33. data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
  34. data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
  35. data/lib/restfulie/client/mikyung/rest_process_model.rb +184 -107
  36. data/lib/restfulie/client/mikyung/steady_state_walker.rb +34 -28
  37. data/lib/restfulie/client/mikyung/then_condition.rb +33 -27
  38. data/lib/restfulie/client/mikyung/when_condition.rb +53 -49
  39. data/lib/restfulie/common.rb +7 -12
  40. data/lib/restfulie/common/converter.rb +20 -9
  41. data/lib/restfulie/common/converter/atom.rb +8 -83
  42. data/lib/restfulie/common/converter/atom/base.rb +89 -0
  43. data/lib/restfulie/common/converter/atom/builder.rb +101 -99
  44. data/lib/restfulie/common/converter/atom/helpers.rb +16 -8
  45. data/lib/restfulie/common/converter/json.rb +12 -0
  46. data/lib/restfulie/common/converter/json/base.rb +84 -0
  47. data/lib/restfulie/common/converter/json/builder.rb +102 -0
  48. data/lib/restfulie/common/converter/json/helpers.rb +17 -0
  49. data/lib/restfulie/common/converter/values.rb +30 -26
  50. data/lib/restfulie/common/converter/xml.rb +14 -0
  51. data/lib/restfulie/common/converter/xml/base.rb +61 -0
  52. data/lib/restfulie/common/converter/xml/builder.rb +112 -0
  53. data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
  54. data/lib/restfulie/common/converter/xml/link.rb +25 -0
  55. data/lib/restfulie/common/converter/xml/links.rb +25 -0
  56. data/lib/restfulie/common/core_ext.rb +1 -5
  57. data/lib/restfulie/common/core_ext/hash.rb +12 -0
  58. data/lib/restfulie/common/error.rb +19 -0
  59. data/lib/restfulie/common/logger.rb +17 -9
  60. data/lib/restfulie/common/representation.rb +9 -10
  61. data/lib/restfulie/common/representation/atom.rb +15 -47
  62. data/lib/restfulie/common/representation/atom/base.rb +122 -365
  63. data/lib/restfulie/common/representation/atom/category.rb +41 -0
  64. data/lib/restfulie/common/representation/atom/entry.rb +52 -100
  65. data/lib/restfulie/common/representation/atom/factory.rb +43 -0
  66. data/lib/restfulie/common/representation/atom/feed.rb +103 -99
  67. data/lib/restfulie/common/representation/atom/link.rb +68 -0
  68. data/lib/restfulie/common/representation/atom/person.rb +48 -0
  69. data/lib/restfulie/common/representation/atom/source.rb +59 -0
  70. data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
  71. data/lib/restfulie/common/representation/atom/xml.rb +95 -0
  72. data/lib/restfulie/common/representation/generic.rb +30 -29
  73. data/lib/restfulie/common/representation/json.rb +10 -22
  74. data/lib/restfulie/common/representation/json/base.rb +27 -0
  75. data/lib/restfulie/common/representation/json/keys_as_methods.rb +72 -0
  76. data/lib/restfulie/common/representation/json/link.rb +29 -0
  77. data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
  78. data/lib/restfulie/common/representation/xml.rb +18 -227
  79. data/lib/restfulie/server.rb +9 -10
  80. data/lib/restfulie/server/action_controller.rb +10 -12
  81. data/lib/restfulie/server/action_controller/base.rb +18 -15
  82. data/lib/restfulie/server/action_controller/{routing/patch.rb → patch.rb} +0 -0
  83. data/lib/restfulie/server/action_controller/restful_responder.rb +43 -35
  84. data/lib/restfulie/server/action_view.rb +8 -6
  85. data/lib/restfulie/server/action_view/helpers.rb +47 -41
  86. data/lib/restfulie/server/action_view/template_handlers.rb +24 -12
  87. data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +17 -12
  88. data/lib/restfulie/server/configuration.rb +22 -19
  89. data/lib/restfulie/server/{restfulie_controller.rb → controller.rb} +1 -10
  90. data/lib/restfulie/server/core_ext.rb +1 -1
  91. data/lib/restfulie/version.rb +14 -0
  92. metadata +52 -16
  93. data/lib/restfulie/client/http/adapter.rb +0 -502
  94. data/lib/restfulie/client/http/atom_ext.rb +0 -4
  95. data/lib/restfulie/client/http/core_ext.rb +0 -6
  96. data/lib/restfulie/client/http/core_ext/http.rb +0 -19
  97. data/lib/restfulie/client/http/marshal.rb +0 -145
  98. data/lib/restfulie/client/http/xml_ext.rb +0 -7
  99. data/lib/restfulie/common/core_ext/proc.rb +0 -48
  100. data/lib/restfulie/common/errors.rb +0 -15
  101. data/lib/restfulie/server/action_controller/routing.rb +0 -12
  102. data/lib/restfulie/server/action_controller/routing/restful_route.rb +0 -14
@@ -1,28 +1,28 @@
1
- module Restfulie::Client::HTTP
2
-
3
- module Cache
4
-
5
- def store
6
- @store || @store = ::ActiveSupport::Cache::MemoryStore.new
7
- end
8
-
9
- def get
10
- store.fetch(@uri) do
11
- request(:get, @uri, @headers)
1
+ module Restfulie
2
+ module Client
3
+ module HTTP
4
+ module Cache
5
+ def store
6
+ @store || @store = ::ActiveSupport::Cache::MemoryStore.new
7
+ end
8
+
9
+ def get
10
+ store.fetch(@uri) do
11
+ request(:get, @uri, @headers)
12
+ end
13
+ end
14
+
15
+ def head
16
+ store.fetch(@uri) do
17
+ request(:head, @uri, @headers)
18
+ end
19
+ end
12
20
  end
13
- end
14
-
15
- def head
16
- store.fetch(@uri) do
17
- request(:head, @uri, @headers)
21
+
22
+ class RequestBuilderExecutorWithCache < RequestBuilderExecutor
23
+ include Cache
18
24
  end
19
25
  end
20
-
21
26
  end
22
-
23
- class RequestBuilderExecutorWithCache < RequestBuilderExecutor
24
- include Cache
25
- end
26
-
27
27
  end
28
28
 
@@ -1,77 +1,77 @@
1
- module Restfulie::Client::HTTP#:nodoc:
2
-
3
- #Client errors
4
- module Error
5
-
1
+ module Restfulie
2
+ module Client
3
+ module HTTP#:nodoc:
4
+ #Client errors
5
+ module Error
6
6
  # Standard error thrown on major client exceptions
7
- class RESTError < StandardError
8
-
9
- attr_reader :response
10
- attr_reader :request
11
-
12
- def initialize(request, response)
13
- @request = request
14
- @response = response
15
- end
16
-
17
- def to_s
18
- "HTTP error #{@response.code} when invoking #{@request.host} via #{@response.method}. " +
19
- ((@response.body.blank?) ? "No additional data was sent." : "The complete response was:\n" + @response.body)
20
- rescue
21
- super
7
+ class RESTError < StandardError
8
+ attr_reader :response
9
+ attr_reader :request
10
+
11
+ def initialize(request, response)
12
+ @request = request
13
+ @response = response
14
+ end
15
+
16
+ def to_s
17
+ "HTTP error #{@response.code} when invoking #{@request.host} via #{@response.method}. " +
18
+ ((@response.body.blank?) ? "No additional data was sent." : "The complete response was:\n" + @response.body)
19
+ rescue
20
+ super
21
+ end
22
22
  end
23
-
24
- end
25
-
26
- class AutoFollowWithoutLocationError < RESTError; end
27
-
28
- #Represents the HTTP code 503
29
- class ServerNotAvailableError < RESTError
30
- def initialize(request, response, exception)
31
- super(request, response)
32
- set_backtrace(exception.backtrace)
23
+
24
+ class AutoFollowWithoutLocationError < RESTError; end
25
+
26
+ # Represents the HTTP code 503
27
+ class ServerNotAvailableError < RESTError
28
+ def initialize(request, response, exception)
29
+ super(request, response)
30
+ set_backtrace(exception.backtrace)
31
+ end
33
32
  end
33
+
34
+ class UnknownError < RESTError; end
35
+
36
+ # Represents the HTTP code 300 range
37
+ class Redirection < RESTError; end
38
+
39
+ class ClientError < RESTError; end
40
+
41
+ # Represents the HTTP code 400
42
+ class BadRequest < ClientError; end
43
+
44
+ # Represents the HTTP code 401
45
+ class Unauthorized < ClientError; end
46
+
47
+ # Represents the HTTP code 403
48
+ class Forbidden < ClientError; end
49
+
50
+ # Represents the HTTP code 404
51
+ class NotFound < ClientError; end
52
+
53
+ # Represents the HTTP code 405
54
+ class MethodNotAllowed < ClientError; end
55
+
56
+ # Represents the HTTP code 412
57
+ class PreconditionFailed < ClientError; end
58
+
59
+ # Represents the HTTP code 407
60
+ class ProxyAuthenticationRequired < ClientError; end
61
+
62
+ # Represents the HTTP code 409
63
+ class Conflict < ClientError; end
64
+
65
+ # Represents the HTTP code 410
66
+ class Gone < ClientError; end
67
+
68
+ # Represents the HTTP code 500
69
+ class ServerError < RESTError; end
70
+
71
+ # Represents the HTTP code 501
72
+ class NotImplemented < ServerError; end
34
73
  end
35
-
36
- class UnknownError < RESTError; end
37
-
38
- #Represents the HTTP code 300 range
39
- class Redirection < RESTError; end
40
-
41
- class ClientError < RESTError; end
42
-
43
- #Represents the HTTP code 400
44
- class BadRequest < ClientError; end
45
-
46
- #Represents the HTTP code 401
47
- class Unauthorized < ClientError; end
48
-
49
- #Represents the HTTP code 403
50
- class Forbidden < ClientError; end
51
-
52
- #Represents the HTTP code 404
53
- class NotFound < ClientError; end
54
-
55
- #Represents the HTTP code 405
56
- class MethodNotAllowed < ClientError; end
57
-
58
- #Represents the HTTP code 412
59
- class PreconditionFailed < ClientError; end
60
-
61
- #Represents the HTTP code 407
62
- class ProxyAuthenticationRequired < ClientError; end
63
-
64
- #Represents the HTTP code 409
65
- class Conflict < ClientError; end
66
-
67
- #Represents the HTTP code 410
68
- class Gone < ClientError; end
69
-
70
- #Represents the HTTP code 500
71
- class ServerError < RESTError; end
72
-
73
- #Represents the HTTP code 501
74
- class NotImplemented < ServerError; end
75
74
  end
75
+ end
76
76
  end
77
77
 
@@ -0,0 +1,15 @@
1
+ module Restfulie
2
+ module Client
3
+ module HTTP
4
+ module LinkRequestBuilder
5
+ include RequestMarshaller
6
+
7
+ def path#:nodoc:
8
+ at(href)
9
+ as(type) if type
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,209 @@
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
+ 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
+ response = ResponseHandler.handle(method, path, get_connection_provider.send(method, path, *args))
146
+ rescue Exception => e
147
+ raise Error::ServerNotAvailableError.new(self, Response.new(method, path, 503, nil, {}), e )
148
+ end
149
+
150
+ case response.code
151
+ when 100..299
152
+ response
153
+ when 300..399
154
+ raise Error::Redirection.new(self, response)
155
+ when 400
156
+ raise Error::BadRequest.new(self, response)
157
+ when 401
158
+ raise Error::Unauthorized.new(self, response)
159
+ when 403
160
+ raise Error::Forbidden.new(self, response)
161
+ when 404
162
+ raise Error::NotFound.new(self, response)
163
+ when 405
164
+ raise Error::MethodNotAllowed.new(self, response)
165
+ when 407
166
+ raise Error::ProxyAuthenticationRequired.new(self, response)
167
+ when 409
168
+ raise Error::Conflict.new(self, response)
169
+ when 410
170
+ raise Error::Gone.new(self, response)
171
+ when 412
172
+ raise Error::PreconditionFailed.new(self, response)
173
+ when 402, 406, 408, 411, 413..499
174
+ raise Error::ClientError.new(self, response)
175
+ when 501
176
+ raise Error::NotImplemented.new(self, response)
177
+ when 500, 502..599
178
+ raise Error::ServerError.new(self, response)
179
+ else
180
+ raise Error::UnknownError.new(self, response)
181
+ end
182
+ end
183
+
184
+ private
185
+
186
+ def get_connection_provider
187
+ @connection ||= ::Net::HTTP.new(@host.host, @host.port)
188
+ end
189
+
190
+ protected
191
+
192
+ def request_to_s(method, path, *args)
193
+ result = ["#{method.to_s.upcase} #{path}"]
194
+
195
+ arguments = args.dup
196
+ headers = arguments.extract_options!
197
+
198
+ if [:post, :put].include?(method)
199
+ body = arguments.shift
200
+ end
201
+
202
+ result << headers.collect { |key, value| "#{key}: #{value}" }.join("\n")
203
+
204
+ (result + [body ? (body.inspect + "\n") : nil]).compact.join("\n") << "\n"
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,107 @@
1
+ module Restfulie
2
+ module Client
3
+ module HTTP #:nodoc:
4
+ # ==== RequestBuilder
5
+ # Uses RequestAdapater to create a HTTP Request DSL
6
+ #
7
+ # ==== Example:
8
+ #
9
+ # @builder = ::Restfulie::Client::HTTP::RequestBuilderExecutor.new("http://restfulie.com") #this class includes RequestBuilder module.
10
+ # @builder.at('/posts').as('application/xml').accepts('application/atom+xml').with('Accept-Language' => 'en').get.code #=> 200
11
+ #
12
+ module RequestBuilder
13
+ include RequestAdapter
14
+
15
+ #Set host
16
+ def at(url)
17
+ self.host = url
18
+ self
19
+ end
20
+
21
+ #Set Content-Type and Accept headers
22
+ def as(content_type)
23
+ headers['Content-Type'] = content_type
24
+ accepts(content_type)
25
+ end
26
+
27
+ #Set Accept headers
28
+ def accepts(content_type)
29
+ headers['Accept'] = content_type
30
+ self
31
+ end
32
+
33
+ # Merge internal header
34
+ #
35
+ # * <tt>headers (e.g. {'Cache-control' => 'no-cache'})</tt>
36
+ #
37
+ def with(headers)
38
+ self.headers.merge!(headers)
39
+ self
40
+ end
41
+
42
+ def headers
43
+ @headers ||= {}
44
+ end
45
+
46
+ # Path (e.g. http://restfulie.com/posts => /posts)
47
+ def path
48
+ host.path
49
+ end
50
+
51
+ def get
52
+ request(:get, path, headers)
53
+ end
54
+
55
+ def head
56
+ request(:head, path, headers)
57
+ end
58
+
59
+ def post(payload)
60
+ request(:post, path, payload, headers)
61
+ end
62
+
63
+ def patch(payload)
64
+ request(:patch, path, payload, headers)
65
+ end
66
+
67
+ def put(payload)
68
+ request(:put, path, payload, headers)
69
+ end
70
+
71
+ def delete
72
+ request(:delete, path, headers)
73
+ end
74
+
75
+ def get!
76
+ request!(:get, path, headers)
77
+ end
78
+
79
+ def head!
80
+ request!(:head, path, headers)
81
+ end
82
+
83
+ def post!(payload)
84
+ request!(:post, path, payload, headers)
85
+ end
86
+
87
+ def patch!(payload)
88
+ request!(:patch, path, payload, headers)
89
+ end
90
+
91
+ def put!(payload)
92
+ request!(:put, path, payload, headers)
93
+ end
94
+
95
+ def delete!
96
+ request!(:delete, path, headers)
97
+ end
98
+
99
+ protected
100
+
101
+ def headers=(h)
102
+ @headers = h
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end