uv-rays 1.2.1 → 1.2.2
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/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
|