footrest 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/footrest.gemspec +2 -1
- data/lib/footrest/http_error.rb +85 -7
- data/lib/footrest/version.rb +1 -1
- data/spec/footrest/http_error_spec.rb +131 -68
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8c6985d2101e71eaaf3391e815b44956a245c6b
|
4
|
+
data.tar.gz: 2fafab4c249ddfcb5681c172e21e3deb88e79368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aaeb3a45a5c52a676ae12112abfd3a1ee10455c33f8b2a09687f4df6ac16228d1aa0b7f43a75be399286fb13400a567561cce2a90e29fc99a91d66aec2bc8b91
|
7
|
+
data.tar.gz: 0ff91ef3cbbaaf112e4a327baf08de84af3188e9bbf60fc0d40553750d4f295b130570e28813d9e1f74eefa9c04606f28f5694f2dc808751fcf846a6a6894517
|
data/footrest.gemspec
CHANGED
@@ -21,9 +21,10 @@ Gem::Specification.new do |gem|
|
|
21
21
|
|
22
22
|
gem.add_development_dependency "rake"
|
23
23
|
gem.add_development_dependency "bundler", ">= 1.0.0"
|
24
|
-
gem.add_development_dependency "rspec", "~>
|
24
|
+
gem.add_development_dependency "rspec", "~> 3.3"
|
25
25
|
gem.add_development_dependency "webmock"
|
26
26
|
gem.add_development_dependency "pry"
|
27
|
+
gem.add_development_dependency "byebug"
|
27
28
|
|
28
29
|
gem.add_dependency "faraday", "~> 0.9.0"
|
29
30
|
gem.add_dependency "activesupport", ">= 3.0.0"
|
data/lib/footrest/http_error.rb
CHANGED
@@ -13,24 +13,20 @@ module Footrest
|
|
13
13
|
@body = @response[:body]
|
14
14
|
@method = @response[:method]
|
15
15
|
|
16
|
-
super("HTTP ERROR: #{
|
16
|
+
super("HTTP ERROR: #{status} (#{status_message}) #{method} #{url}\n#{errors}\n#{headers}")
|
17
17
|
end
|
18
18
|
|
19
19
|
def method
|
20
20
|
@method.to_s.upcase
|
21
|
-
rescue => e
|
22
|
-
"[Unable to show HTTP method: #{e}]"
|
23
21
|
end
|
24
22
|
|
25
23
|
def url
|
26
24
|
@response.url.to_s
|
27
|
-
rescue => e
|
28
|
-
"[Unable to show URL: #{e}]"
|
29
25
|
end
|
30
26
|
|
31
27
|
def headers
|
32
28
|
JSON::pretty_generate(
|
33
|
-
request:
|
29
|
+
request: sanitized_request_headers,
|
34
30
|
response: @response.response_headers
|
35
31
|
)
|
36
32
|
rescue => e
|
@@ -42,6 +38,26 @@ module Footrest
|
|
42
38
|
rescue
|
43
39
|
@body
|
44
40
|
end
|
41
|
+
|
42
|
+
def status_message
|
43
|
+
HTTP_STATUS_CODES.fetch(status, 'UNKNOWN STATUS')
|
44
|
+
end
|
45
|
+
|
46
|
+
def sanitized_request_headers
|
47
|
+
return request_headers unless request_headers['Authorization']
|
48
|
+
request_headers.merge('Authorization' => truncated_authorization_value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def request_headers
|
52
|
+
@response.request_headers
|
53
|
+
end
|
54
|
+
|
55
|
+
def truncated_authorization_value
|
56
|
+
bearer, token = request_headers['Authorization'].split(/\s+/)
|
57
|
+
token_parts = token.split('~')
|
58
|
+
token_parts[-1] = token_parts.last[0, 4]
|
59
|
+
"Bearer #{token_parts.join('~')}..."
|
60
|
+
end
|
45
61
|
end
|
46
62
|
|
47
63
|
%w(
|
@@ -72,4 +88,66 @@ module Footrest
|
|
72
88
|
end
|
73
89
|
end
|
74
90
|
|
75
|
-
|
91
|
+
# Every standard HTTP code mapped to the appropriate message. Ripped directly from
|
92
|
+
# the Rack::Utils source :-)
|
93
|
+
HTTP_STATUS_CODES = {
|
94
|
+
100 => 'Continue',
|
95
|
+
101 => 'Switching Protocols',
|
96
|
+
102 => 'Processing',
|
97
|
+
200 => 'OK',
|
98
|
+
201 => 'Created',
|
99
|
+
202 => 'Accepted',
|
100
|
+
203 => 'Non-Authoritative Information',
|
101
|
+
204 => 'No Content',
|
102
|
+
205 => 'Reset Content',
|
103
|
+
206 => 'Partial Content',
|
104
|
+
207 => 'Multi-Status',
|
105
|
+
208 => 'Already Reported',
|
106
|
+
226 => 'IM Used',
|
107
|
+
300 => 'Multiple Choices',
|
108
|
+
301 => 'Moved Permanently',
|
109
|
+
302 => 'Found',
|
110
|
+
303 => 'See Other',
|
111
|
+
304 => 'Not Modified',
|
112
|
+
305 => 'Use Proxy',
|
113
|
+
307 => 'Temporary Redirect',
|
114
|
+
308 => 'Permanent Redirect',
|
115
|
+
400 => 'Bad Request',
|
116
|
+
401 => 'Unauthorized',
|
117
|
+
402 => 'Payment Required',
|
118
|
+
403 => 'Forbidden',
|
119
|
+
404 => 'Not Found',
|
120
|
+
405 => 'Method Not Allowed',
|
121
|
+
406 => 'Not Acceptable',
|
122
|
+
407 => 'Proxy Authentication Required',
|
123
|
+
408 => 'Request Timeout',
|
124
|
+
409 => 'Conflict',
|
125
|
+
410 => 'Gone',
|
126
|
+
411 => 'Length Required',
|
127
|
+
412 => 'Precondition Failed',
|
128
|
+
413 => 'Payload Too Large',
|
129
|
+
414 => 'URI Too Long',
|
130
|
+
415 => 'Unsupported Media Type',
|
131
|
+
416 => 'Range Not Satisfiable',
|
132
|
+
417 => 'Expectation Failed',
|
133
|
+
421 => 'Misdirected Request',
|
134
|
+
422 => 'Unprocessable Entity',
|
135
|
+
423 => 'Locked',
|
136
|
+
424 => 'Failed Dependency',
|
137
|
+
426 => 'Upgrade Required',
|
138
|
+
428 => 'Precondition Required',
|
139
|
+
429 => 'Too Many Requests',
|
140
|
+
431 => 'Request Header Fields Too Large',
|
141
|
+
500 => 'Internal Server Error',
|
142
|
+
501 => 'Not Implemented',
|
143
|
+
502 => 'Bad Gateway',
|
144
|
+
503 => 'Service Unavailable',
|
145
|
+
504 => 'Gateway Timeout',
|
146
|
+
505 => 'HTTP Version Not Supported',
|
147
|
+
506 => 'Variant Also Negotiates',
|
148
|
+
507 => 'Insufficient Storage',
|
149
|
+
508 => 'Loop Detected',
|
150
|
+
510 => 'Not Extended',
|
151
|
+
511 => 'Network Authentication Required'
|
152
|
+
}
|
153
|
+
end
|
data/lib/footrest/version.rb
CHANGED
@@ -1,99 +1,162 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Footrest
|
4
|
+
describe HttpError do
|
5
|
+
before do
|
6
|
+
@client = Client.new(prefix: "http://domain.com", token: "test_token")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe HttpError::ErrorBase, :focus do
|
10
|
+
let(:response) { Faraday::Env.new(
|
11
|
+
:get,
|
12
|
+
{errors: [{message: "I don't even"}]}.to_json,
|
13
|
+
URI.parse('http://domain.com/api/v1/not_found'),
|
14
|
+
Faraday::RequestOptions.new,
|
15
|
+
{
|
16
|
+
"Accept"=>"application/json",
|
17
|
+
"Authorization"=>"Bearer 365~deadbeef123458792",
|
18
|
+
"User-Agent"=>"Footrest"
|
19
|
+
},
|
20
|
+
Faraday::SSLOptions.new,
|
21
|
+
nil,
|
22
|
+
nil,
|
23
|
+
nil,
|
24
|
+
{"Foo-Bar" => 'baz'},
|
25
|
+
400
|
26
|
+
) }
|
27
|
+
let(:error) { HttpError::ErrorBase.new(response) }
|
28
|
+
|
29
|
+
describe '#initialize(response)' do
|
30
|
+
it 'must include the status code in the message' do
|
31
|
+
expect(error.message).to include '400'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'must include the status message for the status code in the message' do
|
35
|
+
expect(error.message).to include 'Bad Request'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'must include the http method in the request method in the message' do
|
39
|
+
expect(error.message).to include 'GET'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'must include the request url in the message' do
|
43
|
+
expect(error.message).to include 'http://domain.com/api/v1/not_found'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'must include the parsed errors in the message' do
|
47
|
+
expect(error.message).to include "I don't even"
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'must include the response headers in the message' do
|
51
|
+
expect(error.message).to include 'Foo-Bar'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'must include the sanitized request headers in the message' do
|
55
|
+
expect(error.message).to include 'Bearer 365~dead...'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#sanitized_request_headers' do
|
60
|
+
it 'must truncate the value for the Authorization header when it looks like a production Canvas token' do
|
61
|
+
expect(error.sanitized_request_headers).to include 'Authorization' => 'Bearer 365~dead...'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'must truncate the value for the Authorization header when it looks like a generic Bearer token' do
|
65
|
+
response.request_headers['Authorization'] = 'Bearer this-token-is-super-sekret'
|
66
|
+
expect(error.sanitized_request_headers).to include 'Authorization' => 'Bearer this...'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
7
70
|
|
8
|
-
|
9
|
-
|
71
|
+
it "raises a bad request error" do
|
72
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 400)
|
10
73
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
74
|
+
begin
|
75
|
+
@client.get "/api/v1/not_found"
|
76
|
+
rescue Footrest::HttpError::BadRequest => e
|
77
|
+
expect(e.status).to eq(400)
|
78
|
+
end
|
15
79
|
end
|
16
|
-
end
|
17
80
|
|
18
|
-
|
19
|
-
|
81
|
+
it "raises a unauthorized error" do
|
82
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 401)
|
20
83
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
84
|
+
begin
|
85
|
+
@client.get "/api/v1/not_found"
|
86
|
+
rescue Footrest::HttpError::Unauthorized => e
|
87
|
+
expect(e.status).to eq(401)
|
88
|
+
end
|
25
89
|
end
|
26
|
-
end
|
27
90
|
|
28
|
-
|
29
|
-
|
91
|
+
it "raises a forbidden error" do
|
92
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 403)
|
30
93
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
94
|
+
begin
|
95
|
+
@client.get "/api/v1/not_found"
|
96
|
+
rescue Footrest::HttpError::Forbidden => e
|
97
|
+
expect(e.status).to eq(403)
|
98
|
+
end
|
35
99
|
end
|
36
|
-
end
|
37
100
|
|
38
101
|
|
39
|
-
|
40
|
-
|
102
|
+
it "raises a not found error" do
|
103
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 404)
|
41
104
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
105
|
+
begin
|
106
|
+
@client.get "/api/v1/not_found"
|
107
|
+
rescue Footrest::HttpError::NotFound => e
|
108
|
+
expect(e.status).to eq(404)
|
109
|
+
end
|
46
110
|
end
|
47
|
-
end
|
48
111
|
|
49
|
-
|
50
|
-
|
112
|
+
it "raises a method not found allowed" do
|
113
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 405)
|
51
114
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
115
|
+
begin
|
116
|
+
@client.get "/api/v1/not_found"
|
117
|
+
rescue Footrest::HttpError::MethodNotAllowed => e
|
118
|
+
expect(e.status).to eq(405)
|
119
|
+
end
|
56
120
|
end
|
57
|
-
end
|
58
121
|
|
59
|
-
|
60
|
-
|
122
|
+
it "raises a internal server error" do
|
123
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 500)
|
61
124
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
125
|
+
begin
|
126
|
+
@client.get "/api/v1/not_found"
|
127
|
+
rescue Footrest::HttpError::InternalServerError => e
|
128
|
+
expect(e.status).to eq(500)
|
129
|
+
end
|
66
130
|
end
|
67
|
-
end
|
68
131
|
|
69
|
-
|
70
|
-
|
132
|
+
it "raises a not implemented error" do
|
133
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 501)
|
71
134
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
135
|
+
begin
|
136
|
+
@client.get "/api/v1/not_found"
|
137
|
+
rescue Footrest::HttpError::NotImplemented => e
|
138
|
+
expect(e.status).to eq(501)
|
139
|
+
end
|
76
140
|
end
|
77
|
-
end
|
78
141
|
|
79
|
-
|
80
|
-
|
142
|
+
it "raises a bad gateway error" do
|
143
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 502)
|
81
144
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
145
|
+
begin
|
146
|
+
@client.get "/api/v1/not_found"
|
147
|
+
rescue Footrest::HttpError::BadGateway => e
|
148
|
+
expect(e.status).to eq(502)
|
149
|
+
end
|
86
150
|
end
|
87
|
-
end
|
88
151
|
|
89
|
-
|
90
|
-
|
152
|
+
it "raises a Server Unavailible error" do
|
153
|
+
stub_request(:get, "http://domain.com/api/v1/not_found").to_return(:status => 503)
|
91
154
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
155
|
+
begin
|
156
|
+
@client.get "/api/v1/not_found"
|
157
|
+
rescue Footrest::HttpError::ServiceUnavailable => e
|
158
|
+
expect(e.status).to eq(503)
|
159
|
+
end
|
96
160
|
end
|
97
161
|
end
|
98
|
-
|
99
|
-
end
|
162
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: footrest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Duane Johnson
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-08-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '3.3'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '3.3'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: webmock
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +81,20 @@ dependencies:
|
|
81
81
|
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: byebug
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
84
98
|
- !ruby/object:Gem::Dependency
|
85
99
|
name: faraday
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
182
|
version: '0'
|
169
183
|
requirements: []
|
170
184
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.4.5
|
172
186
|
signing_key:
|
173
187
|
specification_version: 4
|
174
188
|
summary: REST APIs
|
@@ -178,3 +192,4 @@ test_files:
|
|
178
192
|
- spec/footrest/pagination_spec.rb
|
179
193
|
- spec/footrest/request_spec.rb
|
180
194
|
- spec/spec_helper.rb
|
195
|
+
has_rdoc:
|