http_wrapper 2.0.0 → 2.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 425cf2e9d257f1b5fa7740175a8f73cb016c3a30
4
- data.tar.gz: ac5befa4cc51dd8ea3370a6ab86bbcb145c37a54
3
+ metadata.gz: a2fa8e4065e61bf929e24793f65c42273fa98884
4
+ data.tar.gz: 4e0efea520c0a5cca574430e3d8cef060004cd60
5
5
  SHA512:
6
- metadata.gz: 5d7ea56a231b668b36017f6f0b12aeab2c76ad83fad1618e6e25736f394445c6537cef1f19d96611408bec41acff5883189308dd93477cd5322e40e9bf6519b2
7
- data.tar.gz: 9b5d9c375e60c37f658a33b54eb4ef4cec6892ce50e36e5399c93bcf7d397f2f3f536e192c2e9189ce35be7ecc0984c6b866c21b65e2815426756c9abbfacbd3
6
+ metadata.gz: 380fa0e02f48cb4affca5d9c74fe54352965bbd6b4630909f509ffddced19f49af661595fce73aa6387e811989ea769d0f93a5ceb31855a60600b0f15b4b7180
7
+ data.tar.gz: 833ada0ed80bd08c7d6313f6e2c07bdc4c9cdb3ee976aac359d8f44420756cbdb45bb2216e09ce8e128351fbbf687ddd625d29315f759fb561803253b3933f27
data/CHANGELOG.md CHANGED
@@ -1,5 +1,100 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.1.0
4
+
5
+ * added ability to perform custom `Net::HTTP` requests
6
+
7
+ ```ruby
8
+ http = HTTPWrapper.new
9
+ uri = URI 'http://example.com'
10
+
11
+ # Ruby v2.0.0
12
+ request = Net::HTTP::Head.new uri
13
+ # Ruby v1.9.3
14
+ request = Net::HTTP::Head.new uri.request_uri
15
+
16
+ http.execute request, uri
17
+ ```
18
+
19
+ * added ability to upload files with `multipart/form-data` content type
20
+
21
+ ```ruby
22
+ http = HTTPWrapper.new
23
+ params = {
24
+ multipart: [
25
+ # ['file input field name', 'File instance or string', {filename: 'itsfile.jpg', content_type: '...'}]
26
+ # last element is optional
27
+ ['user_pic', File.open('user_pic.jpg')],
28
+ ['user_photo', File.read('user_photo.jpg'), {filename: 'photo.jpg'}],
29
+ # you can also specify other parameters
30
+ ['user_name', 'john griffin']
31
+ ],
32
+ # or you can specify other parameters in body section
33
+ # it will be merged with multipart data
34
+ body: {
35
+ user_age: 25
36
+ }
37
+ }
38
+ response = http.post some_url, params
39
+ ```
40
+
41
+ * fixed incorrect content type for `DELETE` request
42
+ * default content type changed to `text/html`
43
+ * added `:user_agent` and `:content_type` shortcuts
44
+
45
+ ```ruby
46
+ # you can specify now user agent like so:
47
+ http = HTTWrapper.new user_agent: 'custom user agent'
48
+ # - or -
49
+ http.user_agent = 'custom user agent'
50
+ http.get sample_url
51
+ # - or -
52
+ http.get sample_url, user_agent: 'custom user agent'
53
+ ```
54
+
55
+ ```ruby
56
+ # you can specify now content type like so:
57
+ http.get sample_url, content_type: 'text/html'
58
+ ```
59
+
60
+ * added ability to specify headers as symbols
61
+
62
+ ```ruby
63
+ http.get some_url, headers: {x_requested_with: 'XMLHttpRequest'}
64
+ # - the same as -
65
+ http.get some_url, headers: {'X-Requested-With' => 'XMLHttpRequest'}
66
+ ```
67
+
68
+ * added ability to fix urls without scheme with default http scheme
69
+
70
+ ```ruby
71
+ http.get 'example.com'
72
+ # will correctly request http://example.com
73
+ ```
74
+
75
+ * added `:max_redirects` option to specify redirect following limits
76
+ * added `:logger` option
77
+
78
+ ```ruby
79
+ log = Logger.new
80
+ http = HTTPWrapper.new logger: log
81
+ - or -
82
+ http.logger = $stdout
83
+ ```
84
+
85
+ * massive refactoring
86
+ * `:ca_file` option removed
87
+ * `:validate_ssl_cert` option renamed to `:verify_cert`
88
+ * `soap` methods removed due to rare usage
89
+ * `:method` key removed from params
90
+ * `:params` key changed to `:query`
91
+
92
+ ```ruby
93
+ http.get some_url, query: { user_id: 1, text: 'abcdefg' }
94
+ ```
95
+
96
+ * fixed bug with timeout - it should be set in seconds, not microseconds
97
+
3
98
  ## v2.0.0
4
99
 
5
100
  * Gem rewritten completely and renamed to 'http_wrapper'
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source 'https://rubygems.org'
2
-
3
2
  gemspec
data/README.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # http_wrapper
2
2
 
3
- Simple wrapper around standard Net::HTTP library to simplify common http[s] tasks usage
3
+ Simple wrapper around standard Net::HTTP library
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/http_wrapper.png)](http://badge.fury.io/rb/http_wrapper)
6
+ [![Build Status](https://travis-ci.org/Svyatov/http_wrapper.png)](https://travis-ci.org/Svyatov/http_wrapper)
7
+ [![Dependency Status](https://gemnasium.com/Svyatov/http_wrapper.png)](https://gemnasium.com/Svyatov/http_wrapper)
8
+ [![Code Climate](https://codeclimate.com/github/Svyatov/http_wrapper.png)](https://codeclimate.com/github/Svyatov/http_wrapper)
9
+ [![Coverage Status](https://coveralls.io/repos/Svyatov/http_wrapper/badge.png)](https://coveralls.io/r/Svyatov/http_wrapper)
10
+
11
+ ---
4
12
 
5
13
  ## Installation
6
14
 
7
15
  Add this line to your Gemfile:
8
16
 
9
- gem 'http_wrapper', '~> 2.0.0'
17
+ ```ruby
18
+ gem 'http_wrapper', '~> 2.1.0'
19
+ ```
10
20
 
11
21
  And then execute:
12
22
 
@@ -32,12 +42,26 @@ http = HTTPWrapper.new
32
42
 
33
43
  ### Access unprotected resource located at **some_url**:
34
44
 
35
- Resource is redirecting? No problem! `http_wrapper` follows up to 10 sequential redirects (you cannot change that limit yet).
45
+ ```ruby
46
+ response = http.get some_url
47
+
48
+ # response is always an instance of Net::HTTPResponse
49
+ ```
50
+
51
+ Resource is redirecting? No problem! `http_wrapper` follows up to 10 sequential redirects by default.
52
+ But you can specify your own limits.
36
53
 
37
54
  ```ruby
55
+ http.max_redirects = 5
38
56
  response = http.get some_url
39
57
  ```
40
58
 
59
+ Url doesn't have scheme? `http_wrapper` prefixes url with `http://` if scheme is missing.
60
+
61
+ ```ruby
62
+ http.get 'example.com' # will correctly request 'http://example.com'
63
+ ```
64
+
41
65
  ### Access resource protected by form-based authentication:
42
66
 
43
67
  1. Post your credentials and get authentication cookie
@@ -48,7 +72,7 @@ response = http.get some_url
48
72
  # credentials as body params
49
73
  cookie = http.post_and_get_cookie some_url, body: { username: 'iamjohn', password: '$uperS1kret' }
50
74
  # - or - credentials as GET query params
51
- cookie = http.post_and_get_cookie some_url, params: { username: 'iamjohn', password: '$uperS1kret' }
75
+ cookie = http.post_and_get_cookie some_url, query: { username: 'iamjohn', password: '$uperS1kret' }
52
76
  ```
53
77
 
54
78
  2. Get protected resource with provided cookie
@@ -69,19 +93,11 @@ response = http.get 'http://example.com', auth: { login: 'iamjohn', password: 'i
69
93
  Add special header or use special method:
70
94
 
71
95
  ```ruby
72
- response = http.get some_url, headers: {'X-Requested-With' => 'XMLHttpRequest'}
73
- # - or -
74
96
  response = http.get_ajax some_url
75
- ```
76
-
77
- ### Access SOAP resource
78
-
79
- Same as before, add special header or use special method:
80
-
81
- ```ruby
82
- response = http.get some_url, headers: {'SOAPAction' => 'someSoapOperation', 'Content-Type' => 'text/xml; charset=UTF-8'}
83
97
  # - or -
84
- response = http.get_soap some_url
98
+ response = http.get some_url, headers: {x_requested_with: 'XMLHttpRequest'}
99
+ # - or -
100
+ response = http.get some_url, headers: {'X-Requested-With' => 'XMLHttpRequest'}
85
101
  ```
86
102
 
87
103
  ### Access JSON resource
@@ -89,9 +105,13 @@ response = http.get_soap some_url
89
105
  Same as before :)
90
106
 
91
107
  ```ruby
92
- response = http.get some_url, headers: {'Content-Type' => 'application/json; charset=UTF-8'}
93
- # - or -
94
108
  response = http.get_json some_url
109
+ # - or -
110
+ response = http.get some_url, content_type: 'application/json; charset=UTF-8'
111
+ # - or -
112
+ response = http.get some_url, headers: {content_type: 'application/json; charset=UTF-8'}
113
+ # - or -
114
+ response = http.get some_url, headers: {'Content-Type' => 'application/json; charset=UTF-8'}
95
115
  ```
96
116
 
97
117
  ### Access JSON resource mimicing AJAX
@@ -115,34 +135,73 @@ response = http.get_json_ajax some_url, some_params
115
135
  Don't worry about escaping, `http_wrapper` got you covered here either.
116
136
 
117
137
  ```ruby
118
- response = http.get 'http://www.google.com', params: {message: 'Hi! M&Ms!', user: 'iamjohn'}
138
+ response = http.get 'http://www.google.com', query: {message: 'Hi! M&Ms!', user: 'iamjohn'}
119
139
  # => http://www.google.com/?message=Hi!%20M%26Ms!&user=iamjohn
120
140
  ```
121
141
 
122
142
  Don't worry about parameters that already in URL, they'll be merged.
123
143
 
124
144
  ```ruby
125
- response = http.get 'http://www.google.com/?q=test', params: {user: 'iamjohn'}
145
+ response = http.get 'http://www.google.com/?q=test', query: {user: 'iamjohn'}
126
146
  # => http://www.google.com/?q=test&user=iamjohn
127
147
  ```
128
148
 
129
- ### Set timeout for wrapper:
149
+ ### Files upload
150
+
151
+ You can easily upload any number of files with `multipart/form-data` content type.
152
+
153
+ ```ruby
154
+ http = HTTPWrapper.new
155
+ params = {
156
+ multipart: [
157
+ # ['file input field name', 'File instance or string', {filename: 'itsfile.jpg', content_type: '...'}]
158
+ ['user_photo', File.read('user_photo.jpg'), {filename: 'photo.jpg'}],
159
+ # last element is optional
160
+ ['user_pic', File.open('user_pic.jpg')],
161
+ # you can also specify other parameters
162
+ ['user_name', 'john griffin']
163
+ ],
164
+ # or you can specify other parameters in body section
165
+ # it will be merged with multipart data
166
+ body: {
167
+ user_age: 25
168
+ }
169
+ }
170
+ response = http.post some_url, params
171
+ ```
172
+
173
+ ### Set timeout
174
+
175
+ By default timeout is set to 10 seconds.
130
176
 
131
177
  ```ruby
132
- http.timeout = 10000 # in milliseconds
178
+ http.timeout = 5 # in seconds
133
179
  # - or - on instantiation
134
- http = HTTPWrapper.new timeout: 10000
180
+ http = HTTPWrapper.new timeout: 5
181
+ ```
182
+
183
+ ### Set logger
184
+
185
+ If you need to debug your requests, it's as simple as to say to `http_wrapper` where to output debug information.
186
+
187
+ ```ruby
188
+ logger = Logger.new '/path/to/log_file'
189
+ http.logger = logger
190
+ # - or -
191
+ http = HTTPWrapper.new logger: $stdout
192
+ # - to switch logger off -
193
+ http.logger = nil
135
194
  ```
136
195
 
137
196
  ### Work over SSL
138
197
 
139
- To work over SSL enable certificate validation before any calls:
198
+ `http_wrapper` works with SSL out of the box and by default verifying domain SSL certificate.
199
+ But you can easily turn verification off if needed.
140
200
 
141
201
  ```ruby
142
- http.validate_ssl_cert = true
143
- http.ca_file = '/path/to/your/ca_file'
202
+ http.verify_cert = false
144
203
  # - or - on instantiation
145
- http = HTTPWrapper.new ca_file: '/path/to/your/ca_file', validate_ssl_cert: true
204
+ http = HTTPWrapper.new verify_cert: false
146
205
  ```
147
206
 
148
207
  ### POST, PUT and DELETE requests
@@ -154,7 +213,7 @@ http.post some_url, body: {user: 'iamjohn', password: 'secret'}
154
213
  # - or -
155
214
  http.put some_url, body: {user: 'iamjohn', password: 'secret'}
156
215
  # - or -
157
- http.delete some_url, params: {user: 'iamjohn'}
216
+ http.delete some_url, query: {user: 'iamjohn'}
158
217
  ```
159
218
 
160
219
  Default content type header for these requests is `application/x-www-form-urlencoded; charset=UTF-8`.
@@ -167,6 +226,33 @@ For `get_json` there are `post_json`, `put_json` and `delete_json`.
167
226
 
168
227
  And for `get_ajax_json`, there are `post_ajax_json`, `put_ajax_json` and `delete_ajax_json`.
169
228
 
229
+ ### Change User Agent
230
+
231
+ ```ruby
232
+ http = HTTWrapper.new user_agent: 'custom user agent'
233
+ # - or -
234
+ http.user_agent = 'custom user agent'
235
+ http.get sample_url
236
+ # - or -
237
+ http.get sample_url, user_agent: 'custom user agent'
238
+ # - or -
239
+ http.get sample_url, headers: { user_agent: 'custom user agent' }
240
+ # the last one always replaces other definitions
241
+ ```
242
+
243
+ ### Perform own custom Net::HTTP requests
244
+
245
+ ```ruby
246
+ uri = URI 'http://example.com'
247
+
248
+ # Ruby 2.0.0
249
+ request = Net::HTTP::Head.new uri
250
+ # Ruby 1.9.3
251
+ request = Net::HTTP::Head.new uri.request_uri
252
+
253
+ http.execute request, uri
254
+ ```
255
+
170
256
  ### Full params hash example
171
257
 
172
258
  ```ruby
@@ -175,11 +261,15 @@ And for `get_ajax_json`, there are `post_ajax_json`, `put_ajax_json` and `delete
175
261
  headers: {
176
262
  'Content-Type' => 'text/html',
177
263
  'X-Requested-With' => 'XMLHttpRequest',
178
- 'User-Agent' => 'Chrome v123'
264
+ 'User-Agent' => 'Chrome v123',
265
+ # - or - use symbols
266
+ content_type: 'text/xml',
267
+ x_requested_with: 'XMLHttpRequest',
268
+ user_agent: 'Chrome v123'
179
269
  },
180
270
 
181
271
  # Query Parameters
182
- params: {
272
+ query: {
183
273
  user: 'iamjohn',
184
274
  'user-stuff' => '123abc'
185
275
  },
@@ -200,13 +290,29 @@ And for `get_ajax_json`, there are `post_ajax_json`, `put_ajax_json` and `delete
200
290
  as: 'a hash'
201
291
  },
202
292
 
203
- # Request method - :get, :post, :put, :delete
204
- :method => :get
293
+ # Shortcut for User-Agent header (headers hash takes precedence)
294
+ user_agent: 'UserAgent v1.2.3',
295
+
296
+ # Shortcut for Content-Type header (headers hash takes precedence)
297
+ content_type: 'text/xml',
298
+
299
+ # multipart/form-data for file uploads
300
+ # the format of array of arrays is important here!
301
+ multipart: [
302
+ # you can use File object
303
+ ['file_input_name', File.open('somefile.ext')],
304
+ # - or - string and specify filename
305
+ ['file_input_name', File.read('somefile.ext'), {filename: 'readme.txt'}],
306
+ # - or - full format
307
+ ['file_input_name', 'some file content', {filename: 'readme.txt', content_type: 'text/text'}],
308
+ # - or - add other simple parameters
309
+ ['user_name', 'john smith']
310
+ ]
205
311
  }
206
312
  ```
207
313
 
208
- Don't worry if you mistype root parameters key. `http_wrapper` checks root params keys and instantiation options keys.
209
- If any unknown options or parameters found, they raise the `UnknownParameterError` exception.
314
+ Don't worry if you mistype root parameters key. `http_wrapper` checks root parameters keys and instantiation options keys.
315
+ If any unknown options or parameters found, it raises the `UnknownParameterError` exception.
210
316
 
211
317
  ## Contributing
212
318
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
2
2
 
3
+ require 'bundler/gem_tasks'
3
4
  require 'rspec/core/rake_task'
4
5
 
5
6
  task :default => :spec
@@ -1,16 +1,20 @@
1
1
  class HTTPWrapper
2
- KNOWN_OPTIONS_KEYS = [:timeout, :ca_file, :validate_ssl_cert].freeze
3
- KNOWN_PARAMS_KEYS = [:headers, :params, :cookie, :auth, :body, :method].freeze
2
+ module HEADER
3
+ CONTENT_TYPE = 'Content-Type'.freeze
4
+ USER_AGENT = 'User-Agent'.freeze
5
+ COOKIE = 'Cookie'.freeze
6
+ AJAX = 'X-Requested-With'.freeze
7
+ end
4
8
 
5
- HEADER_CONTENT_TYPE = 'Content-Type'.freeze
9
+ module CONTENT_TYPE
10
+ DEFAULT = 'text/html; charset=UTF-8'.freeze
11
+ JSON = 'application/json; charset=UTF-8'.freeze
12
+ POST = 'application/x-www-form-urlencoded'.freeze
13
+ MULTIPART = 'multipart/form-data'.freeze
14
+ end
6
15
 
7
- DEFAULT_CONTENT_TYPE = 'text/xml; charset=UTF-8'.freeze
8
- JSON_CONTENT_TYPE = 'application/json; charset=UTF-8'.freeze
9
- POST_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=UTF-8'.freeze
10
-
11
- HEADER_USER_AGENT = 'User-Agent'.freeze
12
- HEADER_COOKIE = 'Cookie'.freeze
13
-
14
- HEADER_AJAX = 'X-Requested-With'.freeze
15
- HEADER_AJAX_VALUE = 'XMLHttpRequest'.freeze
16
+ USER_AGENT = "HTTPWrapper/#{HTTPWrapper::VERSION}; Ruby/#{RUBY_VERSION}".freeze
17
+ AJAX_HEADER = { HEADER::AJAX => 'XMLHttpRequest'.freeze }.freeze
18
+ JSON_HEADER = { HEADER::CONTENT_TYPE => CONTENT_TYPE::JSON }.freeze
19
+ AJAX_JSON_HEADER = AJAX_HEADER.dup.merge!(JSON_HEADER).freeze
16
20
  end
@@ -1,97 +1,35 @@
1
- require 'uri/common'
2
1
  require 'net/https'
3
- require_relative 'constants'
4
- require_relative 'errors'
5
- require_relative 'version'
6
2
 
7
3
  class HTTPWrapper
8
- attr_accessor :timeout, :ca_file, :validate_ssl_cert
4
+ KNOWN_OPTIONS_KEYS = [:timeout, :verify_cert, :logger, :max_redirects, :user_agent].freeze
9
5
 
10
- def initialize(options = {})
11
- unknown_options = options.keys - KNOWN_OPTIONS_KEYS
12
-
13
- if unknown_options.length > 0
14
- raise UnknownParameterError.new "Unknown options: #{unknown_options.join(', ')}"
15
- end
16
-
17
- @timeout = options.fetch(:timeout) { 10000 }
18
- @ca_file = options.fetch(:ca_file) { nil }
19
- @validate_ssl_cert = options.fetch(:validate_ssl_cert) { false }
20
- end
6
+ attr_accessor :timeout, :verify_cert, :logger, :max_redirects, :user_agent
21
7
 
22
- def self.default_user_agent
23
- "HTTPWrapper/#{VERSION}; Ruby/#{RUBY_VERSION}"
24
- end
8
+ def initialize(options = {})
9
+ validate_options options
25
10
 
26
- def get(url, params = {})
27
- params = validate_parameters_and_init_headers params
28
- locate_response url, params
11
+ @timeout = options.fetch(:timeout) { 10 }
12
+ @verify_cert = options.fetch(:verify_cert) { true }
13
+ @logger = options.fetch(:logger) { nil }
14
+ @max_redirects = options.fetch(:max_redirects) { 10 }
15
+ @user_agent = options.fetch(:user_agent) { USER_AGENT }
29
16
  end
30
17
 
31
- [:post, :put, :delete].each do |method|
18
+ [:get, :post, :put, :delete].each do |method|
32
19
  define_method method do |url, params = {}|
33
- params = validate_parameters_and_init_headers params
34
- params[:headers][HEADER_CONTENT_TYPE] ||= POST_CONTENT_TYPE
35
- params[:method] = method
36
- locate_response url, params
37
- end
38
- end
39
-
40
- def get_soap(url, params = {})
41
- params = validate_parameters_and_init_headers params
42
- params[:headers]['SOAPAction'] ||= ''
43
- params[:headers][HEADER_CONTENT_TYPE] ||= DEFAULT_CONTENT_TYPE
44
- locate_response url, params
45
- end
46
-
47
- [:post, :put, :delete].each do |method|
48
- define_method "#{method.to_s}_soap" do |url, params = {}|
49
- params[:method] = method
50
- get_soap url, params
20
+ params[:user_agent] ||= @user_agent
21
+ get_response Request.new(url, method, params)
51
22
  end
52
- end
53
-
54
- def get_ajax(url, params = {})
55
- params = validate_parameters_and_init_headers params
56
- params[:headers][HEADER_AJAX] = HEADER_AJAX_VALUE
57
- locate_response url, params
58
- end
59
-
60
- [:post, :put, :delete].each do |method|
61
- define_method "#{method.to_s}_ajax" do |url, params = {}|
62
- params[:method] = method
63
- get_ajax url, params
64
- end
65
- end
66
-
67
- def get_json(url, params = {})
68
- params = validate_parameters_and_init_headers params
69
- params[:headers][HEADER_CONTENT_TYPE] = JSON_CONTENT_TYPE
70
- locate_response url, params
71
- end
72
23
 
73
- [:post, :put, :delete].each do |method|
74
- define_method "#{method.to_s}_json" do |url, params = {}|
75
- params[:method] = method
76
- get_json url, params
77
- end
78
- end
79
-
80
- def get_ajax_json(url, params = {})
81
- params = validate_parameters_and_init_headers params
82
- params[:headers][HEADER_CONTENT_TYPE] = JSON_CONTENT_TYPE
83
- get_ajax url, params
84
- end
85
-
86
- [:post, :put, :delete].each do |method|
87
- define_method "#{method.to_s}_ajax_json" do |url, params = {}|
88
- params[:method] = method
89
- get_ajax_json url, params
24
+ %w(ajax json ajax_json).each do |header|
25
+ define_method "#{method.to_s}_#{header}" do |url, params = {}|
26
+ params[:headers] ||= {}
27
+ params[:headers].merge! HTTPWrapper.const_get("#{header}_HEADER".upcase)
28
+ __send__ method, url, params
29
+ end
90
30
  end
91
- end
92
31
 
93
- %w(get post put delete).each do |method|
94
- alias_method "#{method}_json_ajax", "#{method}_ajax_json"
32
+ alias_method "#{method.to_s}_json_ajax", "#{method.to_s}_ajax_json"
95
33
  end
96
34
 
97
35
  def post_and_get_cookie(url, params = {})
@@ -99,103 +37,45 @@ class HTTPWrapper
99
37
  response.response['set-cookie']
100
38
  end
101
39
 
40
+ def execute(request, uri)
41
+ connection = create_connection uri
42
+ connection.request request
43
+ end
44
+
102
45
  private
103
46
 
104
- def validate_parameters_and_init_headers(params)
105
- params[:headers] ||= {}
106
- unknown_params = params.keys - KNOWN_PARAMS_KEYS
47
+ def validate_options(options)
48
+ unknown_options = options.keys - KNOWN_OPTIONS_KEYS
107
49
 
108
- if unknown_params.length > 0
109
- raise UnknownParameterError.new "Unknown parameters: #{unknown_params.join(', ')}"
50
+ if unknown_options.length > 0
51
+ raise UnknownParameterError.new "Unknown options: #{unknown_options.join(', ')}"
110
52
  end
111
-
112
- params
113
53
  end
114
54
 
115
- def locate_response(url, params, redirects_limit = 10)
55
+ def get_response(request, redirects_limit = @max_redirects)
116
56
  raise TooManyRedirectsError.new 'Too many redirects!' if redirects_limit == 0
117
57
 
118
- response = execute_request url, params
58
+ response = execute request.create, request.uri
119
59
 
120
60
  if response.kind_of? Net::HTTPRedirection
121
- response = locate_response response['location'], params, redirects_limit - 1
61
+ request.uri = response['location']
62
+ response = get_response request, redirects_limit - 1
122
63
  end
123
64
 
124
65
  response
125
66
  end
126
67
 
127
- def execute_request(url, params)
128
- params[:headers] ||= {}
129
- params[:headers][HEADER_USER_AGENT] ||= self.class.default_user_agent
130
- params[:headers][HEADER_CONTENT_TYPE] ||= DEFAULT_CONTENT_TYPE
131
- params[:headers][HEADER_COOKIE] = params[:cookie] if params[:cookie]
132
-
133
- uri = build_uri url, params[:params]
134
- connection = create_connection uri
135
- request = create_request uri, params
136
-
137
- Timeout.timeout(timeout) do
138
- connection.request(request)
139
- end
140
- end
141
-
142
- def build_uri(url, query_params)
143
- uri = URI url
144
-
145
- if query_params
146
- if uri.query && !uri.query.empty?
147
- new_query = Hash[URI.decode_www_form(uri.query)].merge(query_params)
148
- else
149
- new_query = query_params
150
- end
151
- uri.query = URI.encode_www_form new_query
152
- end
153
-
154
- uri
155
- end
156
-
157
68
  def create_connection(uri)
158
69
  connection = Net::HTTP.new uri.host, uri.port
159
- connection.read_timeout = timeout
160
- connection.open_timeout = timeout
70
+ connection.read_timeout = @timeout
71
+ connection.open_timeout = @timeout
161
72
 
162
- if uri.scheme == 'https'
73
+ if uri.kind_of? URI::HTTPS
163
74
  connection.use_ssl = true
164
-
165
- if validate_ssl_cert
166
- connection.ca_file = ca_file
167
- connection.verify_mode = OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
168
- else
169
- connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
170
- end
75
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @verify_cert
171
76
  end
172
77
 
78
+ connection.set_debug_output(@logger)
173
79
  connection
174
80
  end
175
-
176
- def create_request(uri, params)
177
- case params[:method]
178
- when :get
179
- request = Net::HTTP::Get.new uri.request_uri, params[:headers]
180
- when :post
181
- request = Net::HTTP::Post.new uri.request_uri, params[:headers]
182
- when :put
183
- request = Net::HTTP::Put.new uri.request_uri, params[:headers]
184
- when :delete
185
- request = Net::HTTP::Delete.new uri.request_uri, params[:headers]
186
- else
187
- request = Net::HTTP::Get.new uri.request_uri, params[:headers]
188
- end
189
-
190
- if [:post, :put, :delete].include? params[:method]
191
- request.body = params[:body] if params[:body].kind_of? String
192
- request.set_form_data(params[:body]) if params[:body].kind_of? Hash
193
- end
194
-
195
- if params[:auth]
196
- request.basic_auth params[:auth].fetch(:login), params[:auth].fetch(:password)
197
- end
198
-
199
- request
200
- end
201
81
  end
@@ -0,0 +1,121 @@
1
+ require 'uri/common'
2
+
3
+ class HTTPWrapper
4
+ class Request
5
+ KNOWN_PARAMS_KEYS = [:headers, :query, :cookie, :auth, :body, :user_agent, :content_type, :multipart].freeze
6
+
7
+ def initialize(url, method, params = {})
8
+ validate_parameters params
9
+
10
+ self.uri = url
11
+
12
+ @headers = params[:headers] || {}
13
+ @query = params[:query] || {}
14
+ @cookie = params[:cookie] || @headers[HEADER::COOKIE]
15
+ @login = params[:auth] && params[:auth].fetch(:login)
16
+ @password = params[:auth] && params[:auth].fetch(:password)
17
+
18
+ @method = method
19
+ @method_class = Net::HTTP.const_get(method.to_s.capitalize)
20
+
21
+ @body = params[:body]
22
+ @user_agent = params[:user_agent]
23
+ @content_type = params[:content_type]
24
+
25
+ @multipart_data = params[:multipart] || []
26
+
27
+ initialize_headers
28
+ end
29
+
30
+ attr_reader :uri
31
+
32
+ def uri=(url)
33
+ if url.is_a? URI
34
+ @uri = url
35
+ else
36
+ url = "http://#{url}" unless url =~ /\Ahttps?:\/\//
37
+ @uri = URI.parse url
38
+ end
39
+ end
40
+
41
+ def create
42
+ rebuild_uri_query_params
43
+ convert_symbol_headers_to_string
44
+ create_http_request
45
+ end
46
+
47
+ private
48
+
49
+ def validate_parameters(params)
50
+ unknown_params = params.keys - KNOWN_PARAMS_KEYS
51
+
52
+ if unknown_params.length > 0
53
+ raise UnknownParameterError.new "Unknown parameters: #{unknown_params.join(', ')}"
54
+ end
55
+ end
56
+
57
+ def initialize_headers
58
+ @headers[HEADER::USER_AGENT] ||= @user_agent
59
+ case @method
60
+ when :post, :put then @headers[HEADER::CONTENT_TYPE] ||= (@content_type || CONTENT_TYPE::POST)
61
+ else @headers[HEADER::CONTENT_TYPE] ||= (@content_type || CONTENT_TYPE::DEFAULT)
62
+ end
63
+ end
64
+
65
+ def rebuild_uri_query_params
66
+ return unless @query.size > 0
67
+ query = @uri.query ? query_to_hash(@uri.query).merge(@query) : @query
68
+ @uri.query = URI.encode_www_form query
69
+ end
70
+
71
+ def convert_symbol_headers_to_string
72
+ @headers.keys.select{|key| key.is_a? Symbol}.each do |key|
73
+ str_key = key.to_s.gsub(/_/, '-').capitalize
74
+ @headers[str_key] = @headers.delete key
75
+ end
76
+ end
77
+
78
+ def create_http_request
79
+ # Ruby v1.9.3 doesn't understand full URI object, it needs just path :(
80
+ uri = RUBY_VERSION =~ /\A2/ ? @uri : @uri.request_uri
81
+ @request = @method_class.new uri, @headers
82
+ set_cookies
83
+ set_body
84
+ set_basic_auth
85
+ @request
86
+ end
87
+
88
+ def set_body
89
+ return unless @request.request_body_permitted?
90
+ if @multipart_data.length > 0
91
+ convert_body_to_multipart_data if @body
92
+ @request.set_form @multipart_data, CONTENT_TYPE::MULTIPART
93
+ elsif @body
94
+ @request.body = @body.is_a?(Hash) ? hash_to_query(@body) : @body
95
+ end
96
+ end
97
+
98
+ def set_basic_auth
99
+ return unless @login
100
+ @request.basic_auth @login, @password
101
+ end
102
+
103
+ def set_cookies
104
+ return unless @cookie
105
+ @request['Cookie'] = @cookie
106
+ end
107
+
108
+ def convert_body_to_multipart_data
109
+ @body = query_to_hash(@body) unless @body.kind_of? Hash
110
+ @body.each{|key, value| @multipart_data << [key.to_s, value.to_s]}
111
+ end
112
+
113
+ def query_to_hash(query)
114
+ Hash[URI.decode_www_form query]
115
+ end
116
+
117
+ def hash_to_query(hash)
118
+ URI.encode_www_form hash
119
+ end
120
+ end
121
+ end
@@ -1,3 +1,3 @@
1
1
  class HTTPWrapper
2
- VERSION = '2.0.0'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  end
data/lib/http_wrapper.rb CHANGED
@@ -1 +1,5 @@
1
+ require 'http_wrapper/version'
2
+ require 'http_wrapper/constants'
3
+ require 'http_wrapper/errors'
4
+ require 'http_wrapper/request'
1
5
  require 'http_wrapper/http_wrapper'
@@ -8,7 +8,6 @@ describe HTTPWrapper do
8
8
 
9
9
  it 'should define all dynamic methods' do
10
10
  [:get, :post, :put, :delete,
11
- :get_soap, :post_soap, :put_soap, :delete_soap,
12
11
  :get_json, :post_json, :put_json, :delete_json,
13
12
  :get_ajax, :post_ajax, :put_ajax, :delete_ajax,
14
13
  :get_ajax_json, :post_ajax_json, :put_ajax_json, :delete_ajax_json,
@@ -21,66 +20,134 @@ describe HTTPWrapper do
21
20
  let(:sample_url) { 'http://example.com' }
22
21
  let(:sample_url_with_basic_auth) { "http://#{basic_auth_login}:#{basic_auth_password}@example.com" }
23
22
 
24
- it 'should raise UnknownParameterError if initial options key is unknown' do
25
- expect do
26
- HTTPWrapper.new unknown_option: 'test', maybe_this_known: '?'
27
- end.to raise_error HTTPWrapper::UnknownParameterError, 'Unknown options: unknown_option, maybe_this_known'
28
- end
23
+ context 'Options' do
24
+ it 'should raise UnknownParameterError if initial options key is unknown' do
25
+ expect do
26
+ HTTPWrapper.new unknown_option: 'test', maybe_this_known: '?'
27
+ end.to raise_error HTTPWrapper::UnknownParameterError, 'Unknown options: unknown_option, maybe_this_known'
28
+ end
29
+
30
+ it 'should raise UnknownParameterError if params key is unknown' do
31
+ expect do
32
+ subject.get sample_url, unknown_param_key: 'test', another_param_key: 'wow'
33
+ end.to raise_error HTTPWrapper::UnknownParameterError, 'Unknown parameters: unknown_param_key, another_param_key'
34
+ end
35
+
36
+ it 'should follow redirects no more then 10 times by default' do
37
+ stub_redirects sample_url, 9
38
+ response = subject.get sample_url
39
+ response.code.should eql '200'
40
+
41
+ stub_redirects sample_url, 10
42
+ expect { subject.get sample_url }.to raise_error HTTPWrapper::TooManyRedirectsError, 'Too many redirects!'
43
+ end
44
+
45
+ it 'should follow redirects no more times then specified' do
46
+ subject.max_redirects = 5
29
47
 
30
- it 'should raise UnknownParameterError if params key is unknown' do
31
- expect do
32
- subject.get sample_url, unknown_param_key: 'test', another_param_key: 'wow'
33
- end.to raise_error HTTPWrapper::UnknownParameterError, 'Unknown parameters: unknown_param_key, another_param_key'
48
+ stub_redirects sample_url, 4
49
+ response = subject.get sample_url
50
+ response.code.should eql '200'
51
+
52
+ stub_redirects sample_url, 5
53
+ expect { subject.get sample_url }.to raise_error HTTPWrapper::TooManyRedirectsError, 'Too many redirects!'
54
+ end
55
+
56
+ it 'should use logger' do
57
+ require 'logger'
58
+ logger = Logger.new StringIO.new
59
+ logger.should_receive(:<<).at_least(:once)
60
+ subject.logger = logger
61
+
62
+ WebMock.allow_net_connect!
63
+ begin
64
+ subject.get 'localhost'
65
+ rescue
66
+ # NOOP, rescue from "connection refused" and such
67
+ end
68
+ WebMock.disable_net_connect!
69
+ end
34
70
  end
35
71
 
36
72
  context 'GET' do
73
+ it 'should add http uri scheme if missing' do
74
+ stub_get sample_url
75
+ subject.get sample_url.gsub(/\Ahttp:\/\//, '')
76
+ end
77
+
37
78
  it 'should hit provided url with default content type' do
38
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::DEFAULT_CONTENT_TYPE} }
79
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => HTTPWrapper::CONTENT_TYPE::DEFAULT} }
39
80
  stub_get sample_url, params
40
81
  subject.get sample_url
41
82
  end
42
83
 
43
84
  it 'should set content type if provided' do
44
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => 'Custom Content Type'} }
85
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => 'Custom Content Type'} }
45
86
  stub_get sample_url, params
46
87
  subject.get sample_url, params
88
+ subject.get sample_url, content_type: 'Custom Content Type'
89
+ subject.get sample_url, params.merge({content_type: 'Should Be Overwritten'})
47
90
  end
48
91
 
49
92
  it 'should set proper header for JSON requests' do
50
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::JSON_CONTENT_TYPE} }
93
+ params = { headers: HTTPWrapper::JSON_HEADER }
51
94
  stub_get sample_url, params
52
95
  subject.get_json sample_url
53
96
  end
54
97
 
55
98
  it 'should set proper header for AJAX requests' do
56
- params = { headers: {HTTPWrapper::HEADER_AJAX => HTTPWrapper::HEADER_AJAX_VALUE,
57
- HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::DEFAULT_CONTENT_TYPE } }
99
+ params = {
100
+ headers: {
101
+ HTTPWrapper::HEADER::CONTENT_TYPE => HTTPWrapper::CONTENT_TYPE::DEFAULT
102
+ }.merge(HTTPWrapper::AJAX_HEADER)
103
+ }
58
104
  stub_get sample_url, params
59
105
  subject.get_ajax sample_url
60
106
  end
61
107
 
62
108
  it 'should set proper headers for AJAX-JSON requests' do
63
- params = { headers: {HTTPWrapper::HEADER_AJAX => HTTPWrapper::HEADER_AJAX_VALUE,
64
- HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::JSON_CONTENT_TYPE } }
109
+ params = { headers: HTTPWrapper::AJAX_JSON_HEADER }
65
110
  stub_get sample_url, params
66
111
  subject.get_ajax_json sample_url
67
112
  end
68
113
 
69
114
  it 'should correctly escape query parameters' do
70
115
  stub_get sample_url + '/?param1=&param2=A%26B&param3=C%20%26%20D'
71
- subject.get sample_url, params: {param1: '', param2: 'A&B', param3: 'C & D'}
116
+ subject.get sample_url, query: {param1: '', param2: 'A&B', param3: 'C & D'}
72
117
  end
73
118
 
74
119
  it 'should set default user agent' do
75
- params = { headers: {HTTPWrapper::HEADER_USER_AGENT => HTTPWrapper.default_user_agent} }
120
+ params = { headers: {HTTPWrapper::HEADER::USER_AGENT => HTTPWrapper::USER_AGENT} }
76
121
  stub_get sample_url, params
77
122
  subject.get sample_url
78
123
  end
79
124
 
80
125
  it 'should change user agent if provided' do
81
126
  custom_user_agent = 'Mozilla v1.2.3'
82
- params = { headers: {HTTPWrapper::HEADER_USER_AGENT => custom_user_agent} }
127
+ params = { headers: {HTTPWrapper::HEADER::USER_AGENT => custom_user_agent} }
128
+ stub_get sample_url, params
129
+ subject.get sample_url, params
130
+
131
+ subject.get sample_url, user_agent: custom_user_agent
132
+
133
+ subject.user_agent = custom_user_agent
134
+ subject.get sample_url
135
+
136
+ expect do
137
+ subject.get sample_url, user_agent: 'abracadabra'
138
+ end.to raise_error WebMock::NetConnectNotAllowedError
139
+
140
+ expect do
141
+ subject.user_agent = 'another test'
142
+ subject.get sample_url
143
+ end.to raise_error WebMock::NetConnectNotAllowedError
144
+ end
145
+
146
+ it 'should precedence header user agent before params' do
147
+ params = { headers: {HTTPWrapper::HEADER::USER_AGENT => 'TestUserAgent'} }
83
148
  stub_get sample_url, params
149
+
150
+ subject.user_agent = 'Should Be Overwritten'
84
151
  subject.get sample_url, params
85
152
  end
86
153
 
@@ -97,24 +164,20 @@ describe HTTPWrapper do
97
164
  subject.get sample_url, auth: {login: basic_auth_login, password: basic_auth_password}
98
165
  end
99
166
 
100
- it 'should follow redirects no more then 10 times' do
101
- stub_redirects sample_url, 9
102
- response = subject.get sample_url
103
- response.code.should eql '200'
104
-
105
- stub_redirects sample_url, 10
106
- expect { subject.get sample_url }.to raise_error HTTPWrapper::TooManyRedirectsError, 'Too many redirects!'
107
- end
108
-
109
167
  it 'should merge query parameters and params should take precedence' do
110
168
  stub_get sample_url + '/?text=edf&time=16:44&user=test'
111
- subject.get(sample_url + '/?user=test&text=abc', params: {time: '16:44', text: 'edf'})
169
+ subject.get(sample_url + '/?user=test&text=abc', query: {time: '16:44', text: 'edf'})
170
+ end
171
+
172
+ it 'should equally treat header as string and header as symbol' do
173
+ stub_get sample_url, { headers: {'Content-Type' => 'Some Content Type'} }
174
+ subject.get sample_url, { headers: {content_type: 'Some Content Type'} }
112
175
  end
113
176
  end
114
177
 
115
178
  context 'POST' do
116
179
  it 'should set content type if provided' do
117
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => 'Custom Content Type'} }
180
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => 'Custom Content Type'} }
118
181
  stub_post sample_url, params
119
182
  subject.post sample_url, params
120
183
  end
@@ -128,15 +191,37 @@ describe HTTPWrapper do
128
191
  end
129
192
 
130
193
  it 'should hit provided url with default content type' do
131
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::POST_CONTENT_TYPE } }
194
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => HTTPWrapper::CONTENT_TYPE::POST } }
132
195
  stub_post sample_url, params
133
196
  subject.post sample_url
134
197
  end
198
+
199
+ it 'should set all possible parameters correctly' do
200
+ stub_request(:post, 'http://user:passw@example.com/?a=b&c=d').
201
+ with(body: {
202
+ e: 'f',
203
+ g: 'k'
204
+ },
205
+ headers: {
206
+ 'Content-Type' => 'Custom content type',
207
+ 'User-Agent' => 'Custom user agent',
208
+ 'Cookie' => 'cookie',
209
+ 'X-Requested-With' => 'XMLHttpRequest'
210
+ })
211
+
212
+ subject.post sample_url, content_type: 'Custom content type',
213
+ user_agent: 'Custom user agent',
214
+ headers: {x_requested_with: 'XMLHttpRequest'},
215
+ query: {a: 'b', c: 'd'},
216
+ body: {e: 'f', g: 'k'},
217
+ auth: {login: 'user', password: 'passw'},
218
+ cookie: 'cookie'
219
+ end
135
220
  end
136
221
 
137
222
  context 'PUT' do
138
223
  it 'should hit provided url with default content type' do
139
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::POST_CONTENT_TYPE } }
224
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => HTTPWrapper::CONTENT_TYPE::POST } }
140
225
  stub_put sample_url, params
141
226
  subject.put sample_url
142
227
  end
@@ -144,11 +229,27 @@ describe HTTPWrapper do
144
229
 
145
230
  context 'DELETE' do
146
231
  it 'should hit provided url with default content type' do
147
- params = { headers: {HTTPWrapper::HEADER_CONTENT_TYPE => HTTPWrapper::POST_CONTENT_TYPE } }
232
+ params = { headers: {HTTPWrapper::HEADER::CONTENT_TYPE => HTTPWrapper::CONTENT_TYPE::DEFAULT } }
148
233
  stub_delete sample_url, params
149
234
  subject.delete sample_url
150
235
  end
151
236
  end
237
+
238
+ context 'Custom request instance' do
239
+ it 'should perform request for custom Net::HTTP request instance' do
240
+ stub_request :head, sample_url
241
+ uri = URI sample_url
242
+
243
+ if RUBY_VERSION =~ /\A2/
244
+ request = Net::HTTP::Head.new uri
245
+ subject.execute request, request.uri
246
+ else
247
+ # Ruby v1.9.3 doesn't understand full URI object, it needs just path :(
248
+ request = Net::HTTP::Head.new uri.request_uri
249
+ subject.execute request, uri
250
+ end
251
+ end
252
+ end
152
253
  end
153
254
 
154
255
  context 'HTTPS' do
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  require 'rspec'
2
2
  require 'webmock/rspec'
3
3
 
4
+ if ENV['TRAVIS'] == 'true'
5
+ require 'coveralls'
6
+ Coveralls.wear!
7
+ end
8
+
4
9
  $LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
5
10
 
6
11
  module HTTPWrapperSpecHelpers
@@ -23,6 +28,5 @@ module HTTPWrapperSpecHelpers
23
28
  end
24
29
 
25
30
  RSpec.configure do |config|
26
- config.mock_with :mocha
27
31
  config.include HTTPWrapperSpecHelpers
28
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Svyatov
@@ -9,8 +9,36 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-09 00:00:00.000000000 Z
12
+ date: 2013-09-18 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '10.1'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '10.1'
14
42
  - !ruby/object:Gem::Dependency
15
43
  name: rspec
16
44
  requirement: !ruby/object:Gem::Requirement
@@ -39,8 +67,8 @@ dependencies:
39
67
  - - ~>
40
68
  - !ruby/object:Gem::Version
41
69
  version: 1.13.0
42
- description: Simple wrapper around standard Net::HTTP library to simplify common http[s]
43
- tasks usage
70
+ description: Simple wrapper around standard Net::HTTP library with multipart/form-data
71
+ file upload ability
44
72
  email: leonid@svyatov.ru
45
73
  executables: []
46
74
  extensions: []
@@ -54,6 +82,7 @@ files:
54
82
  - lib/http_wrapper/constants.rb
55
83
  - lib/http_wrapper/errors.rb
56
84
  - lib/http_wrapper/http_wrapper.rb
85
+ - lib/http_wrapper/request.rb
57
86
  - lib/http_wrapper/version.rb
58
87
  - lib/http_wrapper.rb
59
88
  - spec/http_wrapper_spec.rb
@@ -78,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
107
  version: '0'
79
108
  requirements: []
80
109
  rubyforge_project:
81
- rubygems_version: 2.0.7
110
+ rubygems_version: 2.1.4
82
111
  signing_key:
83
112
  specification_version: 4
84
113
  summary: Simple wrapper around standard Net::HTTP library