blanket_wrapper 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -1
- data/lib/blanket/exception.rb +10 -28
- data/lib/blanket/response.rb +6 -9
- data/lib/blanket/version.rb +1 -1
- data/lib/blanket/wrapper.rb +23 -15
- data/spec/blanket/wrapper_spec.rb +30 -0
- metadata +2 -3
- data/LICENSE.txt +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4919971f12da2062b5d5cd9b0152d820acce367
|
4
|
+
data.tar.gz: d5ffa6e823b1a2a00647d13b23a85c78a71b52ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e489971f0588e4d32bc874e22fbe088f13d34cddacd67966e4fb71deb60d234285d8b48c8200114dcb28bdf36cb93654b54bfbf4dc4e0ee8690bd8f5563586d
|
7
|
+
data.tar.gz: 23a7795896868c49f0df75162fc0093f34e9ab63f2f83eb8a09624df8da7c30326cd722fd699922c07db432922ca586da8d79f5e625390b9400c11cb7fd359fc
|
data/README.md
CHANGED
@@ -7,6 +7,19 @@
|
|
7
7
|
|
8
8
|
A dead simple API wrapper.
|
9
9
|
|
10
|
+
**Table of Contents**
|
11
|
+
|
12
|
+
- [Installation](#installation)
|
13
|
+
- [Usage](#usage)
|
14
|
+
- [Quick demo](#quick-demo)
|
15
|
+
- [How it works](#how-it-works)
|
16
|
+
- [Responses](#responses)
|
17
|
+
- [Request Parameters](#request-parameters)
|
18
|
+
- [Headers](#headers)
|
19
|
+
- [Extensions](#extensions)
|
20
|
+
- [Handling Exceptions](#handling-exceptions)
|
21
|
+
- [Contributing](#contributing)
|
22
|
+
|
10
23
|
## Installation
|
11
24
|
|
12
25
|
Add this line to your application's Gemfile:
|
@@ -28,6 +41,8 @@ Or install it yourself as:
|
|
28
41
|
### Quick demo
|
29
42
|
|
30
43
|
```ruby
|
44
|
+
require 'blanket'
|
45
|
+
|
31
46
|
github = Blanket.wrap("https://api.github.com")
|
32
47
|
|
33
48
|
# Get some user's info
|
@@ -104,6 +119,14 @@ repos.map(&:name)
|
|
104
119
|
# => ["analytics-ios", "aztec", "fusebox", ...]
|
105
120
|
```
|
106
121
|
|
122
|
+
### Request Body
|
123
|
+
You can make requests with body using the `body` option:
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
api = Blanket::wrap("http://api.example.org")
|
127
|
+
api.messages.post(body: 'Hello')
|
128
|
+
```
|
129
|
+
|
107
130
|
### Request Parameters
|
108
131
|
Blanket supports appending parameters to your requests:
|
109
132
|
|
@@ -112,6 +135,12 @@ api.users(55).get(params: {foo: 'bar'})
|
|
112
135
|
# => "http://api.example.org/users/55?foo=bar"
|
113
136
|
```
|
114
137
|
|
138
|
+
You can also set default params for all your requests on initialization:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
api = Blanket::wrap("http://api.example.org", params: {access_token: 'my secret token'})
|
142
|
+
```
|
143
|
+
|
115
144
|
### Headers
|
116
145
|
HTTP Headers are always useful when accessing an API, so Blanket makes it easy for you to specify them, either globally or on a per-request basis:
|
117
146
|
|
@@ -157,7 +186,7 @@ end
|
|
157
186
|
|
158
187
|
## Contributing
|
159
188
|
|
160
|
-
1. Fork it ( https://github.com/
|
189
|
+
1. Fork it ( https://github.com/inf0rmer/blanket/fork )
|
161
190
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
162
191
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
163
192
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/lib/blanket/exception.rb
CHANGED
@@ -1,28 +1,7 @@
|
|
1
1
|
module Blanket
|
2
2
|
|
3
|
-
# A Map of HTTP status codes and their names
|
4
|
-
STATUSES = {
|
5
|
-
101 => 'Switching Protocols',
|
6
|
-
102 => 'Processing', #WebDAV
|
7
|
-
|
8
|
-
200 => 'OK',
|
9
|
-
201 => 'Created',
|
10
|
-
202 => 'Accepted',
|
11
|
-
203 => 'Non-Authoritative Information', # http/1.1
|
12
|
-
204 => 'No Content',
|
13
|
-
205 => 'Reset Content',
|
14
|
-
206 => 'Partial Content',
|
15
|
-
207 => 'Multi-Status', #WebDAV
|
16
|
-
|
17
|
-
300 => 'Multiple Choices',
|
18
|
-
301 => 'Moved Permanently',
|
19
|
-
302 => 'Found',
|
20
|
-
303 => 'See Other', # http/1.1
|
21
|
-
304 => 'Not Modified',
|
22
|
-
305 => 'Use Proxy', # http/1.1
|
23
|
-
306 => 'Switch Proxy', # no longer used
|
24
|
-
307 => 'Temporary Redirect', # http/1.1
|
25
|
-
|
3
|
+
# A Map of "error" HTTP status codes and their names
|
4
|
+
STATUSES = {
|
26
5
|
400 => 'Bad Request',
|
27
6
|
401 => 'Unauthorized',
|
28
7
|
402 => 'Payment Required',
|
@@ -101,21 +80,24 @@ module Blanket
|
|
101
80
|
"#{message}: #{body}"
|
102
81
|
end
|
103
82
|
|
104
|
-
|
105
|
-
def to_s
|
106
|
-
inspect
|
107
|
-
end
|
83
|
+
alias_method :to_s, :inspect
|
108
84
|
end
|
109
85
|
|
110
86
|
# We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
111
87
|
module Exceptions
|
112
88
|
# Map http status codes to the corresponding exception class
|
113
89
|
EXCEPTIONS_MAP = {}
|
90
|
+
|
91
|
+
def self.generate_from_response(response)
|
92
|
+
(EXCEPTIONS_MAP[response.code] || Exception).new(response)
|
93
|
+
end
|
114
94
|
end
|
115
95
|
|
116
96
|
STATUSES.each_pair do |code, message|
|
117
97
|
klass = Class.new(Exception) do
|
118
|
-
|
98
|
+
define_method :message do
|
99
|
+
"#{code} #{message}"
|
100
|
+
end
|
119
101
|
end
|
120
102
|
|
121
103
|
klass_constant = const_set message.delete(' \-\''), klass
|
data/lib/blanket/response.rb
CHANGED
@@ -21,22 +21,19 @@ module Blanket
|
|
21
21
|
# Allows accessing the payload's JSON keys through methods.
|
22
22
|
def method_missing(method, *args, &block)
|
23
23
|
if payload.respond_to? method
|
24
|
-
payload.
|
24
|
+
payload.public_send method, *args, &block
|
25
25
|
else
|
26
26
|
super
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
def payload_from_json(json)
|
31
|
-
|
32
|
-
|
33
|
-
RecursiveOpenStruct.new item, :recurse_over_arrays => true
|
34
|
-
end
|
35
|
-
|
36
|
-
(parsed.count == 1) ? parsed.first : parsed
|
37
|
-
else
|
38
|
-
nil
|
31
|
+
parsed = [json].flatten.map do |item|
|
32
|
+
RecursiveOpenStruct.new item, recurse_over_arrays: true
|
39
33
|
end
|
34
|
+
|
35
|
+
(parsed.count == 1) ? parsed.first : parsed
|
40
36
|
end
|
37
|
+
|
41
38
|
end
|
42
39
|
end
|
data/lib/blanket/version.rb
CHANGED
data/lib/blanket/wrapper.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Blanket
|
2
|
-
# The Wrapper class wraps an API
|
3
2
|
class Wrapper
|
4
3
|
class << self
|
5
4
|
private
|
@@ -7,7 +6,7 @@ module Blanket
|
|
7
6
|
# @method $1()
|
8
7
|
# Performs a $1 request on the wrapped URL
|
9
8
|
# @param [String, Symbol, Numeric] id The resource identifier to attach to the last part of the request
|
10
|
-
# @param [Hash] options An options hash with values for :headers, :extension and :
|
9
|
+
# @param [Hash] options An options hash with values for :headers, :extension, :params and :body
|
11
10
|
# @return [Blanket::Response, Array] A wrapped Blanket::Response or an Array
|
12
11
|
def add_action(action)
|
13
12
|
define_method(action) do |id=nil, options={}|
|
@@ -20,6 +19,10 @@ module Blanket
|
|
20
19
|
# should be applied to all requests
|
21
20
|
attr_accessor :headers
|
22
21
|
|
22
|
+
# Attribute accessor for params that
|
23
|
+
# should be applied to all requests
|
24
|
+
attr_accessor :params
|
25
|
+
|
23
26
|
# Attribute accessor for file extension that
|
24
27
|
# should be appended to all requests
|
25
28
|
attr_accessor :extension
|
@@ -32,12 +35,13 @@ module Blanket
|
|
32
35
|
|
33
36
|
# Wraps the base URL for an API
|
34
37
|
# @param [String, Symbol] base_uri The root URL of the API you wish to wrap.
|
35
|
-
# @param [Hash] options An options hash with global values for :headers and :
|
38
|
+
# @param [Hash] options An options hash with global values for :headers, :extension and :params
|
36
39
|
# @return [Blanket] The Blanket object wrapping the API
|
37
40
|
def initialize(base_uri, options={})
|
38
41
|
@base_uri = base_uri
|
39
42
|
@uri_parts = []
|
40
|
-
@headers =
|
43
|
+
@headers = options[:headers] || {}
|
44
|
+
@params = options[:params] || {}
|
41
45
|
@extension = options[:extension]
|
42
46
|
end
|
43
47
|
|
@@ -46,7 +50,8 @@ module Blanket
|
|
46
50
|
def method_missing(method, *args, &block)
|
47
51
|
Wrapper.new uri_from_parts([method, args.first]), {
|
48
52
|
headers: @headers,
|
49
|
-
extension: @extension
|
53
|
+
extension: @extension,
|
54
|
+
params: @params
|
50
55
|
}
|
51
56
|
end
|
52
57
|
|
@@ -57,34 +62,37 @@ module Blanket
|
|
57
62
|
end
|
58
63
|
|
59
64
|
headers = merged_headers(options[:headers])
|
65
|
+
params = merged_params(options[:params])
|
60
66
|
uri = uri_from_parts([id])
|
61
67
|
|
62
68
|
if @extension
|
63
69
|
uri = "#{uri}.#{extension}"
|
64
70
|
end
|
65
71
|
|
66
|
-
response = HTTParty.
|
67
|
-
query:
|
68
|
-
headers: headers
|
69
|
-
|
72
|
+
response = HTTParty.public_send(method, uri, {
|
73
|
+
query: params,
|
74
|
+
headers: headers,
|
75
|
+
body: options[:body]
|
76
|
+
}.reject { |_, value| value.nil? || value.empty? })
|
70
77
|
|
71
78
|
if response.code <= 400
|
72
79
|
body = (response.respond_to? :body) ? response.body : nil
|
73
80
|
(body.is_a? Array) ? body.map(Response.new) : Response.new(body)
|
74
81
|
else
|
75
|
-
raise Blanket::Exceptions
|
82
|
+
raise Blanket::Exceptions.generate_from_response(response)
|
76
83
|
end
|
77
84
|
end
|
78
85
|
|
79
86
|
def merged_headers(headers)
|
80
|
-
|
87
|
+
@headers.merge(headers || {})
|
88
|
+
end
|
89
|
+
|
90
|
+
def merged_params(params)
|
91
|
+
@params.merge(params || {})
|
81
92
|
end
|
82
93
|
|
83
94
|
def uri_from_parts(parts)
|
84
|
-
parts
|
85
|
-
.clone
|
86
|
-
.compact
|
87
|
-
.inject(@base_uri.clone) { |memo, part| memo << "/#{part}" }
|
95
|
+
([@base_uri] + parts).compact.join('/')
|
88
96
|
end
|
89
97
|
end
|
90
98
|
end
|
@@ -45,6 +45,16 @@ describe "Blanket::Wrapper" do
|
|
45
45
|
expect { api.users.get }.to raise_exception(Blanket::InternalServerError)
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
describe "522, a non registered invalid status code" do
|
50
|
+
before :each do
|
51
|
+
stub_request(:get, "http://api.example.org/users").to_return(status: 522, body: "You've been met with a terrible fate, haven't you?")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises a generic instance of Blanket::Exception" do
|
55
|
+
expect { api.users.get }.to raise_exception(Blanket::Exception)
|
56
|
+
end
|
57
|
+
end
|
48
58
|
end
|
49
59
|
|
50
60
|
describe 'Resource identification' do
|
@@ -104,6 +114,13 @@ describe "Blanket::Wrapper" do
|
|
104
114
|
|
105
115
|
expect(HTTParty).to have_received(:get).with('http://api.example.org/users/55', query: {foo: 'bar'})
|
106
116
|
end
|
117
|
+
|
118
|
+
it 'allows setting parameters globally' do
|
119
|
+
api = Blanket::wrap("http://api.example.org", params: {token: 'my secret token'})
|
120
|
+
api.users(55).get(params: {foo: 'bar'})
|
121
|
+
|
122
|
+
expect(HTTParty).to have_received(:get).with('http://api.example.org/users/55', query: {token: 'my secret token', foo: 'bar'})
|
123
|
+
end
|
107
124
|
end
|
108
125
|
|
109
126
|
describe 'URL Extension' do
|
@@ -126,6 +143,19 @@ describe "Blanket::Wrapper" do
|
|
126
143
|
expect(HTTParty).to have_received(:get).with('http://api.example.org/users/55.xml', anything())
|
127
144
|
end
|
128
145
|
end
|
146
|
+
|
147
|
+
describe 'Body' do
|
148
|
+
before :each do
|
149
|
+
allow(HTTParty).to receive(:post) { StubbedResponse.new }
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'allows setting the body for a request' do
|
153
|
+
api = Blanket::wrap("http://api.example.org")
|
154
|
+
api.users(55).post(body: { this_key: :this_value }.to_json)
|
155
|
+
|
156
|
+
expect(HTTParty).to have_received(:post).with('http://api.example.org/users/55', body: { this_key: :this_value }.to_json)
|
157
|
+
end
|
158
|
+
end
|
129
159
|
end
|
130
160
|
|
131
161
|
describe '#get' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blanket_wrapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno Abrantes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -220,7 +220,6 @@ files:
|
|
220
220
|
- Gemfile
|
221
221
|
- Guardfile
|
222
222
|
- LICENSE
|
223
|
-
- LICENSE.txt
|
224
223
|
- README.md
|
225
224
|
- Rakefile
|
226
225
|
- blanket.gemspec
|
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2014 Bruno Abrantes
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|