blanket_wrapper 1.0.1 → 1.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 +4 -4
- data/README.md +23 -2
- data/lib/blanket.rb +5 -3
- data/lib/blanket/exception.rb +124 -0
- data/lib/blanket/response.rb +2 -0
- data/lib/blanket/version.rb +1 -1
- data/lib/blanket/wrapper.rb +7 -3
- data/spec/blanket/exception_spec.rb +106 -0
- data/spec/blanket/wrapper_spec.rb +48 -17
- data/spec/spec_helper.rb +6 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80891d01cd391a6ca57b8cd1d2d266a479529a25
|
4
|
+
data.tar.gz: 8276eaabece824b10f87d5c05bfa043218ca4538
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1206873393b17fc7f110f04d019cc083f0a7b6bd6ef6c2fa2a8ac2741f093b3458d61e5267b5236cefd12f423f7ba2a8b4191ddd0756fc5751f1b5b220652b01
|
7
|
+
data.tar.gz: c6591d74a75cc068784d9fa9e9327f8d6ebcea80265bb8c6ebf30f6e69268dd093dbfcb8d92172b015010bee2a2ed81a182f11b592bcda40292ce84300834b2b
|
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
[](https://travis-ci.org/inf0rmer/blanket)
|
3
3
|
[](https://coveralls.io/r/inf0rmer/blanket?branch=master)
|
4
4
|
[](https://codeclimate.com/github/inf0rmer/blanket)
|
5
|
+
[](http://inch-ci.org/github/inf0rmer/blanket)
|
5
6
|
|
6
7
|
|
7
8
|
A dead simple API wrapper.
|
@@ -11,7 +12,7 @@ A dead simple API wrapper.
|
|
11
12
|
Add this line to your application's Gemfile:
|
12
13
|
|
13
14
|
```ruby
|
14
|
-
gem '
|
15
|
+
gem 'blanket_wrapper'
|
15
16
|
```
|
16
17
|
|
17
18
|
And then execute:
|
@@ -20,7 +21,7 @@ And then execute:
|
|
20
21
|
|
21
22
|
Or install it yourself as:
|
22
23
|
|
23
|
-
$ gem install
|
24
|
+
$ gem install blanket_wrapper
|
24
25
|
|
25
26
|
## Usage
|
26
27
|
|
@@ -134,6 +135,26 @@ users_endpoint = api.users(55)
|
|
134
135
|
users_endpoint.extension = :xml
|
135
136
|
```
|
136
137
|
|
138
|
+
### Handling Exceptions
|
139
|
+
|
140
|
+
Blanket will raise exceptions for HTTP errors encountered while making requests. Exception subclasses are raised for well known errors (404, 500, etc.) but for other status codes a default `Blanket::Exception` will be raised instead.
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
begin
|
144
|
+
api.thingamajig.get
|
145
|
+
rescue Blanket::ResourceNotFound => e
|
146
|
+
e.code
|
147
|
+
# => 404
|
148
|
+
|
149
|
+
e.message
|
150
|
+
# => "404: Resource Not Found"
|
151
|
+
|
152
|
+
# The HTTP body, ie. the error message sent by the server
|
153
|
+
e.body
|
154
|
+
# => "Could not find this resource!"
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
137
158
|
## Contributing
|
138
159
|
|
139
160
|
1. Fork it ( https://github.com/[my-github-username]/blanket/fork )
|
data/lib/blanket.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative "blanket/version"
|
2
|
+
require_relative "blanket/response"
|
3
|
+
require_relative "blanket/exception"
|
4
|
+
require_relative "blanket/wrapper"
|
4
5
|
require 'httparty'
|
5
6
|
|
7
|
+
# The main Blanket module
|
6
8
|
module Blanket
|
7
9
|
# Wraps an API using Blanket::Wrapper
|
8
10
|
def self.wrap(*args)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Blanket
|
2
|
+
|
3
|
+
# A Map of HTTP status codes and their names
|
4
|
+
STATUSES = {100 => 'Continue',
|
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
|
+
|
26
|
+
400 => 'Bad Request',
|
27
|
+
401 => 'Unauthorized',
|
28
|
+
402 => 'Payment Required',
|
29
|
+
403 => 'Forbidden',
|
30
|
+
404 => 'Resource Not Found',
|
31
|
+
405 => 'Method Not Allowed',
|
32
|
+
406 => 'Not Acceptable',
|
33
|
+
407 => 'Proxy Authentication Required',
|
34
|
+
408 => 'Request Timeout',
|
35
|
+
409 => 'Conflict',
|
36
|
+
410 => 'Gone',
|
37
|
+
411 => 'Length Required',
|
38
|
+
412 => 'Precondition Failed',
|
39
|
+
413 => 'Request Entity Too Large',
|
40
|
+
414 => 'Request-URI Too Long',
|
41
|
+
415 => 'Unsupported Media Type',
|
42
|
+
416 => 'Requested Range Not Satisfiable',
|
43
|
+
417 => 'Expectation Failed',
|
44
|
+
418 => 'I\'m A Teapot', #RFC2324
|
45
|
+
421 => 'Too Many Connections From This IP',
|
46
|
+
422 => 'Unprocessable Entity', #WebDAV
|
47
|
+
423 => 'Locked', #WebDAV
|
48
|
+
424 => 'Failed Dependency', #WebDAV
|
49
|
+
425 => 'Unordered Collection', #WebDAV
|
50
|
+
426 => 'Upgrade Required',
|
51
|
+
428 => 'Precondition Required', #RFC6585
|
52
|
+
429 => 'Too Many Requests', #RFC6585
|
53
|
+
431 => 'Request Header Fields Too Large', #RFC6585
|
54
|
+
449 => 'Retry With', #Microsoft
|
55
|
+
450 => 'Blocked By Windows Parental Controls', #Microsoft
|
56
|
+
|
57
|
+
500 => 'Internal Server Error',
|
58
|
+
501 => 'Not Implemented',
|
59
|
+
502 => 'Bad Gateway',
|
60
|
+
503 => 'Service Unavailable',
|
61
|
+
504 => 'Gateway Timeout',
|
62
|
+
505 => 'HTTP Version Not Supported',
|
63
|
+
506 => 'Variant Also Negotiates',
|
64
|
+
507 => 'Insufficient Storage', #WebDAV
|
65
|
+
509 => 'Bandwidth Limit Exceeded', #Apache
|
66
|
+
510 => 'Not Extended',
|
67
|
+
511 => 'Network Authentication Required', # RFC6585
|
68
|
+
}
|
69
|
+
|
70
|
+
# The base class for all Blanket Exceptions
|
71
|
+
class Exception < RuntimeError
|
72
|
+
# Attribute writer for the Exception message
|
73
|
+
attr_writer :message
|
74
|
+
# Attribute reader for the Exception http response
|
75
|
+
attr_reader :response
|
76
|
+
|
77
|
+
# Creates a new exception
|
78
|
+
# @param [HTTParty::Response] response the HTTP Response
|
79
|
+
# @return [Blanket::Exception] The Blanket Exception object
|
80
|
+
def initialize(response = nil)
|
81
|
+
@response = response
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the HTTP response body
|
85
|
+
def body
|
86
|
+
@response.body.to_s if @response
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the HTTP status code
|
90
|
+
def code
|
91
|
+
@response.code.to_i if @response
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns a formatted error message
|
95
|
+
def message
|
96
|
+
@message || self.class.name
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns a stringified error message
|
100
|
+
def inspect
|
101
|
+
"#{message}: #{body}"
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns a stringified error message
|
105
|
+
def to_s
|
106
|
+
inspect
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
111
|
+
module Exceptions
|
112
|
+
# Map http status codes to the corresponding exception class
|
113
|
+
EXCEPTIONS_MAP = {}
|
114
|
+
end
|
115
|
+
|
116
|
+
STATUSES.each_pair do |code, message|
|
117
|
+
klass = Class.new(Exception) do
|
118
|
+
send(:define_method, :message) {"#{code ? "#{code} " : ''}#{message}"}
|
119
|
+
end
|
120
|
+
|
121
|
+
klass_constant = const_set message.delete(' \-\''), klass
|
122
|
+
Exceptions::EXCEPTIONS_MAP[code] = klass_constant
|
123
|
+
end
|
124
|
+
end
|
data/lib/blanket/response.rb
CHANGED
data/lib/blanket/version.rb
CHANGED
data/lib/blanket/wrapper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Blanket
|
2
|
+
# The Wrapper class wraps an API
|
2
3
|
class Wrapper
|
3
4
|
class << self
|
4
5
|
private
|
@@ -67,9 +68,12 @@ module Blanket
|
|
67
68
|
headers: headers
|
68
69
|
}.reject { |k, v| v.nil? || v.empty? })
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
if response.code <= 400
|
72
|
+
body = (response.respond_to? :body) ? response.body : nil
|
73
|
+
(body.is_a? Array) ? body.map(Response.new) : Response.new(body)
|
74
|
+
else
|
75
|
+
raise Blanket::Exceptions::EXCEPTIONS_MAP[response.code].new(response)
|
76
|
+
end
|
73
77
|
end
|
74
78
|
|
75
79
|
def merged_headers(headers)
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'blanket/exception'
|
3
|
+
|
4
|
+
describe Blanket::Exception do
|
5
|
+
describe "#message" do
|
6
|
+
context "When a message is not set" do
|
7
|
+
let :e do
|
8
|
+
Blanket::Exception.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns its Class name" do
|
12
|
+
expect(e.message).to eq("Blanket::Exception")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "When a message is set" do
|
17
|
+
let :message do
|
18
|
+
"A custom exception message"
|
19
|
+
end
|
20
|
+
|
21
|
+
let :e do
|
22
|
+
e = Blanket::Exception.new
|
23
|
+
e.message = message
|
24
|
+
e
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns the custom message" do
|
28
|
+
expect(e.message).to eq(message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#response" do
|
34
|
+
let :response do
|
35
|
+
double("HTTP Response", code: 500)
|
36
|
+
end
|
37
|
+
|
38
|
+
let :e do
|
39
|
+
Blanket::InternalServerError.new(response)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows access to the HTTP status code" do
|
43
|
+
expect(e.response).to eq(response)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#code" do
|
48
|
+
let :response do
|
49
|
+
double("HTTP Response", code: 500)
|
50
|
+
end
|
51
|
+
|
52
|
+
let :e do
|
53
|
+
Blanket::InternalServerError.new(response)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "allows access to the HTTP status code" do
|
57
|
+
expect(e.code).to eq(response.code)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#body" do
|
62
|
+
let :body do
|
63
|
+
"Internal Server Error"
|
64
|
+
end
|
65
|
+
|
66
|
+
let :response do
|
67
|
+
double("HTTP Response", code: 500, body: body)
|
68
|
+
end
|
69
|
+
|
70
|
+
let :e do
|
71
|
+
Blanket::InternalServerError.new(response)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "allows access to the HTTP response body" do
|
75
|
+
expect(e.body).to eq(body)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Blanket::ResourceNotFound do
|
81
|
+
let :e do
|
82
|
+
e = Blanket::ResourceNotFound.new
|
83
|
+
end
|
84
|
+
|
85
|
+
it "inherits from Blanket::Exception" do
|
86
|
+
expect(e).to be_kind_of(Blanket::Exception)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "has a '404 Resource Not Found' message" do
|
90
|
+
expect(e.message).to eq("404 Resource Not Found")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe Blanket::InternalServerError do
|
95
|
+
let :e do
|
96
|
+
e = Blanket::InternalServerError.new
|
97
|
+
end
|
98
|
+
|
99
|
+
it "inherits from Blanket::Exception" do
|
100
|
+
expect(e).to be_kind_of(Blanket::Exception)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "has a '500 Internal Server Error' message" do
|
104
|
+
expect(e.message).to eq("500 Internal Server Error")
|
105
|
+
end
|
106
|
+
end
|
@@ -7,11 +7,9 @@ describe "Blanket::Wrapper" do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe 'Making Requests' do
|
10
|
-
before :each do
|
11
|
-
allow(HTTParty).to receive(:get)
|
12
|
-
end
|
13
|
-
|
14
10
|
it 'resets after performing a request' do
|
11
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
12
|
+
|
15
13
|
api.users.get()
|
16
14
|
api.videos.get()
|
17
15
|
|
@@ -20,11 +18,12 @@ describe "Blanket::Wrapper" do
|
|
20
18
|
|
21
19
|
describe "Response" do
|
22
20
|
before :each do
|
23
|
-
stub_request(:get, "http://api.example.org/users")
|
21
|
+
stub_request(:get, "http://api.example.org/users")
|
22
|
+
.to_return(:body => '{"title": "Something"}')
|
24
23
|
end
|
25
24
|
|
26
25
|
let :response do
|
27
|
-
api.users.get
|
26
|
+
api.users.get
|
28
27
|
end
|
29
28
|
|
30
29
|
it "returns a Blanket::Response instance" do
|
@@ -32,7 +31,27 @@ describe "Blanket::Wrapper" do
|
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
34
|
+
describe "Exceptions" do
|
35
|
+
let :api do
|
36
|
+
Blanket::wrap("http://api.example.org")
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "500" do
|
40
|
+
before :each do
|
41
|
+
stub_request(:get, "http://api.example.org/users").to_return(:status => 500, :body => "You've been met with a terrible fate, haven't you?")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "raises a Blanket::InternalServerError exception" do
|
45
|
+
expect { api.users.get }.to raise_exception(Blanket::InternalServerError)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
35
50
|
describe 'Resource identification' do
|
51
|
+
before do
|
52
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
53
|
+
end
|
54
|
+
|
36
55
|
context 'When using a resource method' do
|
37
56
|
it 'allows identifying a resource' do
|
38
57
|
api.users(55).get()
|
@@ -57,6 +76,10 @@ describe "Blanket::Wrapper" do
|
|
57
76
|
end
|
58
77
|
|
59
78
|
describe 'Headers' do
|
79
|
+
before :each do
|
80
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
81
|
+
end
|
82
|
+
|
60
83
|
it 'allows sending headers in a request' do
|
61
84
|
api.users(55).get(headers: {foo: 'bar'})
|
62
85
|
|
@@ -72,6 +95,10 @@ describe "Blanket::Wrapper" do
|
|
72
95
|
end
|
73
96
|
|
74
97
|
describe 'Parameters' do
|
98
|
+
before :each do
|
99
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
100
|
+
end
|
101
|
+
|
75
102
|
it 'allows sending parameters in a request' do
|
76
103
|
api.users(55).get(params: {foo: 'bar'})
|
77
104
|
|
@@ -80,7 +107,11 @@ describe "Blanket::Wrapper" do
|
|
80
107
|
end
|
81
108
|
|
82
109
|
describe 'URL Extension' do
|
83
|
-
|
110
|
+
before :each do
|
111
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'allows setting an extension for a request' do
|
84
115
|
users_endpoint = api.users(55)
|
85
116
|
users_endpoint.extension = :json
|
86
117
|
users_endpoint.get
|
@@ -98,8 +129,8 @@ describe "Blanket::Wrapper" do
|
|
98
129
|
end
|
99
130
|
|
100
131
|
describe '#get' do
|
101
|
-
before
|
102
|
-
allow(HTTParty).to receive(:get)
|
132
|
+
before do
|
133
|
+
allow(HTTParty).to receive(:get) { StubbedResponse.new }
|
103
134
|
end
|
104
135
|
|
105
136
|
it 'GETs a resource' do
|
@@ -110,8 +141,8 @@ describe "Blanket::Wrapper" do
|
|
110
141
|
end
|
111
142
|
|
112
143
|
describe '#post' do
|
113
|
-
before
|
114
|
-
allow(HTTParty).to receive(:post)
|
144
|
+
before do
|
145
|
+
allow(HTTParty).to receive(:post) { StubbedResponse.new }
|
115
146
|
end
|
116
147
|
|
117
148
|
it 'POSTs a resource' do
|
@@ -122,8 +153,8 @@ describe "Blanket::Wrapper" do
|
|
122
153
|
end
|
123
154
|
|
124
155
|
describe '#put' do
|
125
|
-
before
|
126
|
-
allow(HTTParty).to receive(:put)
|
156
|
+
before do
|
157
|
+
allow(HTTParty).to receive(:put) { StubbedResponse.new }
|
127
158
|
end
|
128
159
|
|
129
160
|
it 'PUTs a resource' do
|
@@ -134,8 +165,8 @@ describe "Blanket::Wrapper" do
|
|
134
165
|
end
|
135
166
|
|
136
167
|
describe '#patch' do
|
137
|
-
before
|
138
|
-
allow(HTTParty).to receive(:patch)
|
168
|
+
before do
|
169
|
+
allow(HTTParty).to receive(:patch) { StubbedResponse.new }
|
139
170
|
end
|
140
171
|
|
141
172
|
it 'PATCHes a resource' do
|
@@ -146,8 +177,8 @@ describe "Blanket::Wrapper" do
|
|
146
177
|
end
|
147
178
|
|
148
179
|
describe '#delete' do
|
149
|
-
before
|
150
|
-
allow(HTTParty).to receive(:delete)
|
180
|
+
before do
|
181
|
+
allow(HTTParty).to receive(:delete) { StubbedResponse.new }
|
151
182
|
end
|
152
183
|
|
153
184
|
it 'DELETEs a resource' do
|
data/spec/spec_helper.rb
CHANGED
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.0
|
4
|
+
version: 1.1.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: 2014-12-
|
11
|
+
date: 2014-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -225,9 +225,11 @@ files:
|
|
225
225
|
- Rakefile
|
226
226
|
- blanket.gemspec
|
227
227
|
- lib/blanket.rb
|
228
|
+
- lib/blanket/exception.rb
|
228
229
|
- lib/blanket/response.rb
|
229
230
|
- lib/blanket/version.rb
|
230
231
|
- lib/blanket/wrapper.rb
|
232
|
+
- spec/blanket/exception_spec.rb
|
231
233
|
- spec/blanket/response_spec.rb
|
232
234
|
- spec/blanket/wrapper_spec.rb
|
233
235
|
- spec/blanket_spec.rb
|
@@ -257,6 +259,7 @@ signing_key:
|
|
257
259
|
specification_version: 4
|
258
260
|
summary: A dead simple API wrapper. Access your data with style.
|
259
261
|
test_files:
|
262
|
+
- spec/blanket/exception_spec.rb
|
260
263
|
- spec/blanket/response_spec.rb
|
261
264
|
- spec/blanket/wrapper_spec.rb
|
262
265
|
- spec/blanket_spec.rb
|