skylight 0.0.5 → 0.0.6

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.
@@ -1,140 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- module Errors
5
-
6
- class Error < StandardError; end
7
- class StubNotFound < StandardError; end
8
-
9
- class SocketError < Error
10
- attr_reader :socket_error
11
-
12
- def initialize(socket_error=nil)
13
- if socket_error.message =~ /certificate verify failed/
14
- super('Unable to verify certificate, please set `Excon.defaults[:ssl_ca_path] = path_to_certs`, `Excon.defaults[:ssl_ca_file] = path_to_file`, or `Excon.defaults[:ssl_verify_peer] = false` (less secure).')
15
- else
16
- super("#{socket_error.message} (#{socket_error.class})")
17
- end
18
- set_backtrace(socket_error.backtrace)
19
- @socket_error = socket_error
20
- end
21
- end
22
-
23
- class Timeout < Error; end
24
-
25
- class ProxyParseError < Error; end
26
-
27
- class ProxyConnectionError < Error; end
28
-
29
- class HTTPStatusError < Error
30
- attr_reader :request, :response
31
-
32
- def initialize(msg, request = nil, response = nil)
33
- super(msg)
34
- @request = request
35
- @response = response
36
- end
37
- end
38
-
39
- class Continue < HTTPStatusError; end # 100
40
- class SwitchingProtocols < HTTPStatusError; end # 101
41
- class OK < HTTPStatusError; end # 200
42
- class Created < HTTPStatusError; end # 201
43
- class Accepted < HTTPStatusError; end # 202
44
- class NonAuthoritativeInformation < HTTPStatusError; end # 203
45
- class NoContent < HTTPStatusError; end # 204
46
- class ResetContent < HTTPStatusError; end # 205
47
- class PartialContent < HTTPStatusError; end # 206
48
- class MultipleChoices < HTTPStatusError; end # 300
49
- class MovedPermanently < HTTPStatusError; end # 301
50
- class Found < HTTPStatusError; end # 302
51
- class SeeOther < HTTPStatusError; end # 303
52
- class NotModified < HTTPStatusError; end # 304
53
- class UseProxy < HTTPStatusError; end # 305
54
- class TemporaryRedirect < HTTPStatusError; end # 307
55
- class BadRequest < HTTPStatusError; end # 400
56
- class Unauthorized < HTTPStatusError; end # 401
57
- class PaymentRequired < HTTPStatusError; end # 402
58
- class Forbidden < HTTPStatusError; end # 403
59
- class NotFound < HTTPStatusError; end # 404
60
- class MethodNotAllowed < HTTPStatusError; end # 405
61
- class NotAcceptable < HTTPStatusError; end # 406
62
- class ProxyAuthenticationRequired < HTTPStatusError; end # 407
63
- class RequestTimeout < HTTPStatusError; end # 408
64
- class Conflict < HTTPStatusError; end # 409
65
- class Gone < HTTPStatusError; end # 410
66
- class LengthRequired < HTTPStatusError; end # 411
67
- class PreconditionFailed < HTTPStatusError; end # 412
68
- class RequestEntityTooLarge < HTTPStatusError; end # 413
69
- class RequestURITooLong < HTTPStatusError; end # 414
70
- class UnsupportedMediaType < HTTPStatusError; end # 415
71
- class RequestedRangeNotSatisfiable < HTTPStatusError; end # 416
72
- class ExpectationFailed < HTTPStatusError; end # 417
73
- class UnprocessableEntity < HTTPStatusError; end # 422
74
- class InternalServerError < HTTPStatusError; end # 500
75
- class NotImplemented < HTTPStatusError; end # 501
76
- class BadGateway < HTTPStatusError; end # 502
77
- class ServiceUnavailable < HTTPStatusError; end # 503
78
- class GatewayTimeout < HTTPStatusError; end # 504
79
-
80
- # Messages for nicer exceptions, from rfc2616
81
- def self.status_error(request, response)
82
- @errors ||= {
83
- 100 => [Excon::Errors::Continue, 'Continue'],
84
- 101 => [Excon::Errors::SwitchingProtocols, 'Switching Protocols'],
85
- 200 => [Excon::Errors::OK, 'OK'],
86
- 201 => [Excon::Errors::Created, 'Created'],
87
- 202 => [Excon::Errors::Accepted, 'Accepted'],
88
- 203 => [Excon::Errors::NonAuthoritativeInformation, 'Non-Authoritative Information'],
89
- 204 => [Excon::Errors::NoContent, 'No Content'],
90
- 205 => [Excon::Errors::ResetContent, 'Reset Content'],
91
- 206 => [Excon::Errors::PartialContent, 'Partial Content'],
92
- 300 => [Excon::Errors::MultipleChoices, 'Multiple Choices'],
93
- 301 => [Excon::Errors::MovedPermanently, 'Moved Permanently'],
94
- 302 => [Excon::Errors::Found, 'Found'],
95
- 303 => [Excon::Errors::SeeOther, 'See Other'],
96
- 304 => [Excon::Errors::NotModified, 'Not Modified'],
97
- 305 => [Excon::Errors::UseProxy, 'Use Proxy'],
98
- 307 => [Excon::Errors::TemporaryRedirect, 'Temporary Redirect'],
99
- 400 => [Excon::Errors::BadRequest, 'Bad Request'],
100
- 401 => [Excon::Errors::Unauthorized, 'Unauthorized'],
101
- 402 => [Excon::Errors::PaymentRequired, 'Payment Required'],
102
- 403 => [Excon::Errors::Forbidden, 'Forbidden'],
103
- 404 => [Excon::Errors::NotFound, 'Not Found'],
104
- 405 => [Excon::Errors::MethodNotAllowed, 'Method Not Allowed'],
105
- 406 => [Excon::Errors::NotAcceptable, 'Not Acceptable'],
106
- 407 => [Excon::Errors::ProxyAuthenticationRequired, 'Proxy Authentication Required'],
107
- 408 => [Excon::Errors::RequestTimeout, 'Request Timeout'],
108
- 409 => [Excon::Errors::Conflict, 'Conflict'],
109
- 410 => [Excon::Errors::Gone, 'Gone'],
110
- 411 => [Excon::Errors::LengthRequired, 'Length Required'],
111
- 412 => [Excon::Errors::PreconditionFailed, 'Precondition Failed'],
112
- 413 => [Excon::Errors::RequestEntityTooLarge, 'Request Entity Too Large'],
113
- 414 => [Excon::Errors::RequestURITooLong, 'Request-URI Too Long'],
114
- 415 => [Excon::Errors::UnsupportedMediaType, 'Unsupported Media Type'],
115
- 416 => [Excon::Errors::RequestedRangeNotSatisfiable, 'Request Range Not Satisfiable'],
116
- 417 => [Excon::Errors::ExpectationFailed, 'Expectation Failed'],
117
- 422 => [Excon::Errors::UnprocessableEntity, 'Unprocessable Entity'],
118
- 500 => [Excon::Errors::InternalServerError, 'InternalServerError'],
119
- 501 => [Excon::Errors::NotImplemented, 'Not Implemented'],
120
- 502 => [Excon::Errors::BadGateway, 'Bad Gateway'],
121
- 503 => [Excon::Errors::ServiceUnavailable, 'Service Unavailable'],
122
- 504 => [Excon::Errors::GatewayTimeout, 'Gateway Timeout']
123
- }
124
-
125
- error, message = @errors[response[:status]] || [Excon::Errors::HTTPStatusError, 'Unknown']
126
-
127
- # scrub authorization
128
- request = request.dup
129
- request.reject! {|key, value| [:connection, :stack].include?(key)}
130
- if request.has_key?(:headers) && request[:headers].has_key?('Authorization')
131
- request[:headers] = request[:headers].dup
132
- request[:headers]['Authorization'] = REDACTED
133
- end
134
- error.new("Expected(#{request[:expects].inspect}) <=> Actual(#{response[:status]} #{message})\n request => #{request.inspect}\n response => #{response.inspect}", request, response)
135
- end
136
-
137
- end
138
- end
139
- end
140
- end
@@ -1,23 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- module Middleware
5
- class Base
6
- def initialize(stack)
7
- @stack = stack
8
- end
9
-
10
- def request_call(datum)
11
- # do stuff
12
- @stack.request_call(datum)
13
- end
14
-
15
- def response_call(datum)
16
- @stack.response_call(datum)
17
- # do stuff
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,22 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- module Middleware
5
- class Expects < Excon::Middleware::Base
6
- def response_call(datum)
7
- if datum.has_key?(:expects) && ![*datum[:expects]].include?(datum[:response][:status])
8
- raise(
9
- Excon::Errors.status_error(
10
- datum.reject {|key,value| key == :response},
11
- datum[:response]
12
- )
13
- )
14
- else
15
- @stack.response_call(datum)
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,31 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- module Middleware
5
- class Instrumentor < Excon::Middleware::Base
6
- def request_call(datum)
7
- if datum.has_key?(:instrumentor)
8
- if datum[:retries_remaining] < datum[:retry_limit]
9
- event_name = "#{datum[:instrumentor_name]}.retry"
10
- else
11
- event_name = "#{datum[:instrumentor_name]}.request"
12
- end
13
- datum[:instrumentor].instrument(event_name, datum) do
14
- @stack.request_call(datum)
15
- end
16
- else
17
- @stack.request_call(datum)
18
- end
19
- end
20
-
21
- def response_call(datum)
22
- if datum.has_key?(:instrumentor)
23
- datum[:instrumentor].instrument("#{datum[:instrumentor_name]}.response", datum[:response])
24
- end
25
- @stack.response_call(datum)
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,88 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- module Middleware
5
- class Mock < Excon::Middleware::Base
6
- def request_call(datum)
7
- if datum[:mock]
8
- # convert File/Tempfile body to string before matching:
9
- unless datum[:body].nil? || datum[:body].is_a?(String)
10
- if datum[:body].respond_to?(:binmode)
11
- datum[:body].binmode
12
- end
13
- if datum[:body].respond_to?(:rewind)
14
- datum[:body].rewind
15
- end
16
- datum[:body] = datum[:body].read
17
- end
18
-
19
- datum[:captures] = {:headers => {}} # setup data to hold captures
20
- Excon.stubs.each do |stub, response|
21
- headers_match = !stub.has_key?(:headers) || stub[:headers].keys.all? do |key|
22
- case value = stub[:headers][key]
23
- when Regexp
24
- if match = value.match(datum[:headers][key])
25
- datum[:captures][:headers][key] = match.captures
26
- end
27
- match
28
- else
29
- value == datum[:headers][key]
30
- end
31
- end
32
- non_headers_match = (stub.keys - [:headers]).all? do |key|
33
- case value = stub[key]
34
- when Regexp
35
- if match = value.match(datum[key])
36
- datum[:captures][key] = match.captures
37
- end
38
- match
39
- else
40
- value == datum[key]
41
- end
42
- end
43
- if headers_match && non_headers_match
44
- datum[:response] = {
45
- :body => '',
46
- :headers => {},
47
- :status => 200,
48
- :remote_ip => '127.0.0.1'
49
- }
50
-
51
- stub_datum = case response
52
- when Proc
53
- response.call(datum)
54
- else
55
- response
56
- end
57
-
58
- datum[:response].merge!(stub_datum.reject {|key,value| key == :headers})
59
- if stub_datum.has_key?(:headers)
60
- datum[:response][:headers].merge!(stub_datum[:headers])
61
- end
62
-
63
- if datum[:expects] && ![*datum[:expects]].include?(datum[:response][:status])
64
- # don't pass stuff into a block if there was an error
65
- elsif datum.has_key?(:response_block) && datum[:response].has_key?(:body)
66
- body = datum[:response].delete(:body)
67
- content_length = remaining = body.bytesize
68
- i = 0
69
- while i < body.length
70
- datum[:response_block].call(body[i, datum[:chunk_size]], [remaining - datum[:chunk_size], 0].max, content_length)
71
- remaining -= datum[:chunk_size]
72
- i += datum[:chunk_size]
73
- end
74
- end
75
- return @stack.request_call(datum)
76
- end
77
- end
78
- # if we reach here no stubs matched
79
- raise(Excon::Errors::StubNotFound.new('no stubs matched ' << datum.inspect))
80
- else
81
- @stack.request_call(datum)
82
- end
83
- end
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,68 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- class Response
5
-
6
- attr_accessor :data
7
-
8
- # backwards compatability reader/writers
9
- def body=(new_body)
10
- @data[:body] = new_body
11
- end
12
- def body
13
- @data[:body]
14
- end
15
- def headers=(new_headers)
16
- @data[:headers] = new_headers
17
- end
18
- def headers
19
- @data[:headers]
20
- end
21
- def status=(new_status)
22
- @data[:status] = new_status
23
- end
24
- def status
25
- @data[:status]
26
- end
27
- def remote_ip=(new_remote_ip)
28
- @data[:remote_ip] = new_remote_ip
29
- end
30
- def remote_ip
31
- @data[:remote_ip]
32
- end
33
-
34
- def initialize(params={})
35
- @data = {
36
- :body => '',
37
- :headers => {}
38
- }.merge(params)
39
- @body = @data[:body]
40
- @headers = @data[:headers]
41
- @status = @data[:status]
42
- @remote_ip = @data[:remote_ip]
43
- end
44
-
45
- def [](key)
46
- @data[key]
47
- end
48
-
49
- def params
50
- $stderr.puts("Excon::Response#params is deprecated use Excon::Response#data instead (#{caller.first})")
51
- data
52
- end
53
-
54
- # Retrieve a specific header value. Header names are treated case-insensitively.
55
- # @param [String] name Header name
56
- def get_header(name)
57
- headers.each do |key,value|
58
- if key.casecmp(name) == 0
59
- return value
60
- end
61
- end
62
- nil
63
- end
64
-
65
- end # class Response
66
- end # module Excon
67
- end
68
- end
@@ -1,206 +0,0 @@
1
- module Skylight
2
- module Vendor
3
- module Excon
4
- class Socket
5
-
6
- extend Forwardable
7
-
8
- attr_accessor :data
9
-
10
- def params
11
- $stderr.puts("Excon::Socket#params is deprecated use Excon::Socket#data instead (#{caller.first})")
12
- @data
13
- end
14
- def params=(new_params)
15
- $stderr.puts("Excon::Socket#params= is deprecated use Excon::Socket#data= instead (#{caller.first})")
16
- @data = new_params
17
- end
18
-
19
- attr_reader :remote_ip
20
-
21
- def_delegators(:@socket, :close, :close)
22
- def_delegators(:@socket, :readline, :readline)
23
-
24
- def initialize(data = {})
25
- @data = data
26
- @read_buffer = ''
27
- @eof = false
28
-
29
- @data[:family] ||= ::Socket::Constants::AF_UNSPEC
30
- if @data[:proxy]
31
- @data[:proxy][:family] ||= ::Socket::Constants::AF_UNSPEC
32
- end
33
-
34
- connect
35
- end
36
-
37
- def connect
38
- @socket = nil
39
- exception = nil
40
-
41
- addrinfo = if @data[:proxy]
42
- ::Socket.getaddrinfo(@data[:proxy][:host], @data[:proxy][:port], @data[:proxy][:family], ::Socket::Constants::SOCK_STREAM)
43
- else
44
- ::Socket.getaddrinfo(@data[:host], @data[:port], @data[:family], ::Socket::Constants::SOCK_STREAM)
45
- end
46
-
47
- addrinfo.each do |_, port, _, ip, a_family, s_type|
48
- @remote_ip = ip
49
-
50
- # nonblocking connect
51
- begin
52
- sockaddr = ::Socket.sockaddr_in(port, ip)
53
-
54
- socket = ::Socket.new(a_family, s_type, 0)
55
-
56
- if @data[:nonblock]
57
- socket.connect_nonblock(sockaddr)
58
- else
59
- begin
60
- Timeout.timeout(@data[:connect_timeout]) do
61
- socket.connect(sockaddr)
62
- end
63
- rescue Timeout::Error
64
- raise Excon::Errors::Timeout.new('connect timeout reached')
65
- end
66
- end
67
-
68
- @socket = socket
69
- break
70
- rescue Errno::EINPROGRESS
71
- unless IO.select(nil, [socket], nil, @data[:connect_timeout])
72
- raise(Excon::Errors::Timeout.new("connect timeout reached"))
73
- end
74
- begin
75
- socket.connect_nonblock(sockaddr)
76
-
77
- @socket = socket
78
- break
79
- rescue Errno::EISCONN
80
- @socket = socket
81
- break
82
- rescue SystemCallError => exception
83
- socket.close
84
- next
85
- end
86
- rescue SystemCallError => exception
87
- socket.close
88
- next
89
- end
90
- end
91
-
92
- unless @socket
93
- # this will be our last encountered exception
94
- raise exception
95
- end
96
- end
97
-
98
- def read(max_length=nil)
99
- if @eof
100
- return nil
101
- elsif @data[:nonblock]
102
- begin
103
- if max_length
104
- until @read_buffer.length >= max_length
105
- @read_buffer << @socket.read_nonblock(max_length - @read_buffer.length)
106
- end
107
- else
108
- while true
109
- @read_buffer << @socket.read_nonblock(@data[:chunk_size])
110
- end
111
- end
112
- rescue OpenSSL::SSL::SSLError => error
113
- if error.message == 'read would block'
114
- if IO.select([@socket], nil, nil, @data[:read_timeout])
115
- retry
116
- else
117
- raise(Excon::Errors::Timeout.new("read timeout reached"))
118
- end
119
- else
120
- raise(error)
121
- end
122
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
123
- if IO.select([@socket], nil, nil, @data[:read_timeout])
124
- retry
125
- else
126
- raise(Excon::Errors::Timeout.new("read timeout reached"))
127
- end
128
- rescue EOFError
129
- @eof = true
130
- end
131
- if max_length
132
- @read_buffer.slice!(0, max_length)
133
- else
134
- # read until EOFError, so return everything
135
- @read_buffer.slice!(0, @read_buffer.length)
136
- end
137
- else
138
- begin
139
- Timeout.timeout(@data[:read_timeout]) do
140
- @socket.read(max_length)
141
- end
142
- rescue Timeout::Error
143
- raise Excon::Errors::Timeout.new('read timeout reached')
144
- end
145
- end
146
- end
147
-
148
- def write(data)
149
- if @data[:nonblock]
150
- # We normally return from the return in the else block below, but
151
- # we guard that data is still something in case we get weird
152
- # values and String#[] returns nil. (This behavior has been observed
153
- # in the wild, so this is a simple defensive mechanism)
154
- while data
155
- begin
156
- # I wish that this API accepted a start position, then we wouldn't
157
- # have to slice data when there is a short write.
158
- written = @socket.write_nonblock(data)
159
- rescue OpenSSL::SSL::SSLError => error
160
- if error.message == 'write would block'
161
- if IO.select(nil, [@socket], nil, @data[:write_timeout])
162
- retry
163
- else
164
- raise(Excon::Errors::Timeout.new("write timeout reached"))
165
- end
166
- else
167
- raise(error)
168
- end
169
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable
170
- if IO.select(nil, [@socket], nil, @data[:write_timeout])
171
- retry
172
- else
173
- raise(Excon::Errors::Timeout.new("write timeout reached"))
174
- end
175
- else
176
- # Fast, common case.
177
- # The >= seems weird, why would it have written MORE than we
178
- # requested. But we're getting some weird behavior when @socket
179
- # is an OpenSSL socket, where it seems like it's saying it wrote
180
- # more (perhaps due to SSL packet overhead?).
181
- #
182
- # Pretty weird, but this is a simple defensive mechanism.
183
- return if written >= data.size
184
-
185
- # This takes advantage of the fact that most ruby implementations
186
- # have Copy-On-Write strings. Thusly why requesting a subrange
187
- # of data, we actually don't copy data because the new string
188
- # simply references a subrange of the original.
189
- data = data[written, data.size]
190
- end
191
- end
192
- else
193
- begin
194
- Timeout.timeout(@data[:write_timeout]) do
195
- @socket.write(data)
196
- end
197
- rescue Timeout::Error
198
- Excon::Errors::Timeout.new('write timeout reached')
199
- end
200
- end
201
- end
202
-
203
- end
204
- end
205
- end
206
- end