footrest 0.5.0 → 0.5.1
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/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:
|