uv-rays 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/uv-rays/http/request.rb +19 -8
- data/lib/uv-rays/http/response.rb +4 -1
- data/lib/uv-rays/http_endpoint.rb +42 -3
- data/lib/uv-rays/version.rb +1 -1
- data/spec/http_endpoint_spec.rb +63 -0
- data/uv-rays.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 058dd2e60b392b41bd8138d396022069f087f730
|
4
|
+
data.tar.gz: 3ba1ec427f37ccbc321c38cd1cd6ed7021dbfaf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4d0275064097f22c4b3a955f55874ede3735dd7315bd120d2a0b01ad89c497af88523a516df2d9ac2b984295ff907fb1174b2c7c90120f266a6699278318227
|
7
|
+
data.tar.gz: 35110447fbce49124c2f5592d9caa35e8e17368f6a1831084213131ad3dbd106f39edae90c395ead4d3e3f7968d638e871445cb31c7a6f2b6af2650daa124b82
|
data/lib/uv-rays/http/request.rb
CHANGED
@@ -11,7 +11,7 @@ module UV
|
|
11
11
|
|
12
12
|
attr_reader :path
|
13
13
|
attr_reader :method
|
14
|
-
attr_reader :headers
|
14
|
+
attr_reader :headers, :options
|
15
15
|
|
16
16
|
|
17
17
|
def cookies_hash
|
@@ -23,22 +23,32 @@ module UV
|
|
23
23
|
end
|
24
24
|
|
25
25
|
|
26
|
-
def initialize(endpoint, options)
|
26
|
+
def initialize(endpoint, options, using_ntlm)
|
27
27
|
super(endpoint.loop, endpoint.loop.defer)
|
28
28
|
|
29
29
|
@options = options
|
30
30
|
@endpoint = endpoint
|
31
|
+
@ntlm_retries = using_ntlm ? 0 : nil
|
31
32
|
|
32
33
|
@path = options[:path]
|
33
34
|
@method = options[:method]
|
34
35
|
@uri = "#{endpoint.scheme}#{encode_host(endpoint.host, endpoint.port)}#{@path}"
|
35
36
|
end
|
36
37
|
|
37
|
-
def resolve(response)
|
38
|
-
@
|
39
|
-
headers: @headers
|
40
|
-
|
41
|
-
|
38
|
+
def resolve(response, body)
|
39
|
+
if @ntlm_retries && @headers.status == 401 && @headers[:"WWW-Authenticate"] && @ntlm_retries < 3
|
40
|
+
@options[:headers][:Authorization] = @endpoint.ntlm_auth_header(@headers[:"WWW-Authenticate"])
|
41
|
+
@ntlm_retries += 1
|
42
|
+
|
43
|
+
response.request = self
|
44
|
+
execute(*@exec_params)
|
45
|
+
else
|
46
|
+
@exec_params = nil
|
47
|
+
@defer.resolve({
|
48
|
+
headers: @headers,
|
49
|
+
body: body
|
50
|
+
})
|
51
|
+
end
|
42
52
|
end
|
43
53
|
|
44
54
|
def reject(reason)
|
@@ -47,6 +57,7 @@ module UV
|
|
47
57
|
|
48
58
|
def execute(transport, error)
|
49
59
|
head, body = build_request, @options[:body]
|
60
|
+
@exec_params = [transport, error]
|
50
61
|
|
51
62
|
@endpoint.middleware.each do |m|
|
52
63
|
head, body = m.request(self, head, body) if m.respond_to?(:request)
|
@@ -79,7 +90,7 @@ module UV
|
|
79
90
|
|
80
91
|
if body
|
81
92
|
request_header << body
|
82
|
-
transport.write(
|
93
|
+
transport.write(request_header).catch error
|
83
94
|
elsif file
|
84
95
|
transport.write(request_header).catch error
|
85
96
|
|
@@ -110,11 +110,14 @@ module UV
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def on_message_complete(parser)
|
113
|
-
@request
|
113
|
+
req = @request
|
114
|
+
bod = @body
|
114
115
|
|
115
116
|
# Clean up memory
|
116
117
|
@request = nil
|
117
118
|
@body = nil
|
119
|
+
|
120
|
+
req.resolve(self, bod)
|
118
121
|
end
|
119
122
|
|
120
123
|
# We need to flush the response on disconnect if content-length is undefined
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'rubyntlm'
|
2
|
+
|
3
|
+
|
1
4
|
module UV
|
2
5
|
class CookieJar
|
3
6
|
def initialize
|
@@ -51,7 +54,7 @@ module UV
|
|
51
54
|
|
52
55
|
def initialize(uri, options = {})
|
53
56
|
@inactivity_timeout = options[:inactivity_timeout] ||= 10000 # default connection inactivity (post-setup) timeout
|
54
|
-
|
57
|
+
@ntlm_creds = options[:ntlm]
|
55
58
|
|
56
59
|
uri = uri.kind_of?(Addressable::URI) ? uri : Addressable::URI::parse(uri.to_s)
|
57
60
|
@https = uri.scheme == "https"
|
@@ -102,7 +105,7 @@ module UV
|
|
102
105
|
options[:method] = method
|
103
106
|
|
104
107
|
# Setup the request with callbacks
|
105
|
-
request = Http::Request.new(self, options)
|
108
|
+
request = Http::Request.new(self, options, @ntlm_creds)
|
106
109
|
request.then(proc { |result|
|
107
110
|
@waiting_response = nil
|
108
111
|
|
@@ -212,6 +215,13 @@ module UV
|
|
212
215
|
@response.request = @staging_request
|
213
216
|
@staging_request = nil
|
214
217
|
|
218
|
+
if @ntlm_creds
|
219
|
+
opts = @waiting_response.options
|
220
|
+
opts[:headers] ||= {}
|
221
|
+
opts = opts[:headers]
|
222
|
+
opts[:Authorization] = ntlm_auth_header
|
223
|
+
end
|
224
|
+
|
215
225
|
@timer.again if @inactivity_timeout > 0
|
216
226
|
@waiting_response.execute(@transport, proc { |err|
|
217
227
|
@transport.close
|
@@ -242,7 +252,30 @@ module UV
|
|
242
252
|
reqs.each do |request|
|
243
253
|
request.reject(:close_connection)
|
244
254
|
end
|
245
|
-
super(after_writing)
|
255
|
+
super(after_writing) if @transport
|
256
|
+
end
|
257
|
+
|
258
|
+
def ntlm_auth_header(challenge = nil)
|
259
|
+
if @ntlm_auth && challenge.nil?
|
260
|
+
return @ntlm_auth
|
261
|
+
elsif challenge
|
262
|
+
scheme, param_str = parse_ntlm_challenge_header(challenge)
|
263
|
+
if param_str.nil?
|
264
|
+
@ntlm_auth = nil
|
265
|
+
return ntlm_auth_header(creds)
|
266
|
+
else
|
267
|
+
t2 = Net::NTLM::Message.decode64(param_str)
|
268
|
+
t3 = t2.response(@ntlm_creds, ntlmv2: true)
|
269
|
+
@ntlm_auth = "NTLM #{t3.encode64}"
|
270
|
+
return @ntlm_auth
|
271
|
+
end
|
272
|
+
else
|
273
|
+
domain = @ntlm_creds[:domain]
|
274
|
+
t1 = Net::NTLM::Message::Type1.new()
|
275
|
+
t1.domain = domain if domain
|
276
|
+
@ntlm_auth = "NTLM #{t1.encode64}"
|
277
|
+
return @ntlm_auth
|
278
|
+
end
|
246
279
|
end
|
247
280
|
|
248
281
|
|
@@ -257,5 +290,11 @@ module UV
|
|
257
290
|
def stop_timer
|
258
291
|
@timer.stop unless @timer.nil?
|
259
292
|
end
|
293
|
+
|
294
|
+
def parse_ntlm_challenge_header(challenge)
|
295
|
+
scheme, param_str = challenge.scan(/\A(\S+)(?:\s+(.*))?\z/)[0]
|
296
|
+
return nil if scheme.nil?
|
297
|
+
return scheme, param_str
|
298
|
+
end
|
260
299
|
end
|
261
300
|
end
|
data/lib/uv-rays/version.rb
CHANGED
data/spec/http_endpoint_spec.rb
CHANGED
@@ -20,6 +20,33 @@ module HttpServer
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
module NTLMServer
|
24
|
+
def post_init
|
25
|
+
@parser = ::HttpParser::Parser.new(self)
|
26
|
+
@state = ::HttpParser::Parser.new_instance
|
27
|
+
@state.type = :request
|
28
|
+
|
29
|
+
@req = 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_message_complete(parser)
|
33
|
+
if @req == 0
|
34
|
+
@state = ::HttpParser::Parser.new_instance
|
35
|
+
write("HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: NTLM TlRMTVNTUAACAAAAEgASADgAAAAFgokCuEPycVw6htsAAAAAAAAAAK4ArgBKAAAABgOAJQAAAA9SAEEAQgBPAE4ARQBUAE8AQwACABIAUgBBAEIATwBOAEUAVABPAEMAAQAUAFMAWQBQAFYAMQA5ADkAMAA1ADUABAAcAG8AYwAuAHIAYQBiAG8AbgBlAHQALgBjAG8AbQADADIAUwBZAFAAVgAxADkAOQAwADUANQAuAG8AYwAuAHIAYQBiAG8AbgBlAHQALgBjAG8AbQAFABYAcgBhAGIAbwBuAGUAdAAuAGMAbwBtAAcACACcZNzCwkbRAQAAAAA=\r\nContent-type: text/html\r\nContent-length: 0\r\n\r\n")
|
36
|
+
else
|
37
|
+
write("HTTP/1.1 200 OK\r\nContent-type: text/html\r\nContent-length: 1\r\n\r\ny")
|
38
|
+
end
|
39
|
+
@req += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_read(data, connection)
|
43
|
+
if @parser.parse(@state, data)
|
44
|
+
p 'parse error'
|
45
|
+
p @state.error
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
23
50
|
module OldServer
|
24
51
|
def post_init
|
25
52
|
@parser = ::HttpParser::Parser.new(self)
|
@@ -201,4 +228,40 @@ describe UV::HttpEndpoint do
|
|
201
228
|
expect(@response2[:headers].keep_alive).to eq(false)
|
202
229
|
end
|
203
230
|
end
|
231
|
+
|
232
|
+
describe 'NTLM auth support' do
|
233
|
+
it "should perform NTLM auth transparently" do
|
234
|
+
@loop.run { |logger|
|
235
|
+
logger.progress do |level, errorid, error|
|
236
|
+
begin
|
237
|
+
@general_failure << "Log called: #{level}: #{errorid}\n#{error.message}\n#{error.backtrace.join("\n")}\n"
|
238
|
+
rescue Exception
|
239
|
+
@general_failure << 'error in logger'
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
tcp = UV.start_server '127.0.0.1', 3250, NTLMServer
|
244
|
+
server = UV::HttpEndpoint.new 'http://127.0.0.1:3250', ntlm: {
|
245
|
+
user: 'username',
|
246
|
+
password: 'password',
|
247
|
+
domain: 'domain'
|
248
|
+
}
|
249
|
+
|
250
|
+
request = server.get(path: '/')
|
251
|
+
request.then(proc { |response|
|
252
|
+
@response = response
|
253
|
+
tcp.close
|
254
|
+
@loop.stop
|
255
|
+
}, @request_failure)
|
256
|
+
}
|
257
|
+
|
258
|
+
expect(@general_failure).to eq([])
|
259
|
+
expect(@response[:headers][:"Content-type"]).to eq('text/html')
|
260
|
+
expect(@response[:headers].http_version).to eq('1.1')
|
261
|
+
expect(@response[:headers].status).to eq(200)
|
262
|
+
expect(@response[:headers].cookies).to eq({})
|
263
|
+
expect(@response[:headers].keep_alive).to eq(true)
|
264
|
+
expect(@response[:body]).to eq('y')
|
265
|
+
end
|
266
|
+
end
|
204
267
|
end
|
data/uv-rays.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |gem|
|
|
20
20
|
gem.add_runtime_dependency 'ipaddress'
|
21
21
|
gem.add_runtime_dependency 'addressable'
|
22
22
|
gem.add_runtime_dependency 'http-parser', '>= 1.0.4'
|
23
|
+
gem.add_runtime_dependency 'rubyntlm'
|
23
24
|
|
24
25
|
gem.add_development_dependency 'rspec', '>= 2.14'
|
25
26
|
gem.add_development_dependency 'rake', '>= 10.1'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uv-rays
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen von Takach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: libuv
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.0.4
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubyntlm
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: rspec
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|