blanket_wrapper 1.0.1 → 1.1.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 +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
|
[![Build Status](https://travis-ci.org/inf0rmer/blanket.svg?branch=master)](https://travis-ci.org/inf0rmer/blanket)
|
3
3
|
[![Coverage Status](https://img.shields.io/coveralls/inf0rmer/blanket.svg)](https://coveralls.io/r/inf0rmer/blanket?branch=master)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/inf0rmer/blanket/badges/gpa.svg)](https://codeclimate.com/github/inf0rmer/blanket)
|
5
|
+
[![Inline docs](http://inch-ci.org/github/inf0rmer/blanket.svg?branch=master)](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
|