skylight 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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