class UV::Http::Request
Constants
- CONNECTION
- COOKIE
- CRLF
Attributes
method[R]
options[R]
path[R]
Public Class Methods
new(endpoint, options)
click to toggle source
Calls superclass method
# File lib/uv-rays/http/request.rb, line 32 def initialize(endpoint, options) super(endpoint.thread, endpoint.thread.defer) @host = endpoint.host @port = endpoint.port @http_proxy = endpoint.http_proxy? ? endpoint.proxy : nil @encoded_host = endpoint.encoded_host path = options[:path] if path.is_a?(::URI) @path = path.to_s.split(@encoded_host)[1] || '/' else @path = path end @method = options[:method] @cookiejar = endpoint.cookiejar @middleware = endpoint.middleware @uri = "#{endpoint.scheme}://#{@encoded_host}#{@path}" @path = @uri if @http_proxy endpoint = nil @options = options @ntlm_creds = options[:ntlm] @digest_creds = options[:digest] @challenge_retries = 0 # Don't hold references to vars we don't require anymore self.finally { @host = @port = nil @cookiejar = nil @middleware = nil } @error = proc { |reason| reject(reason) } end
Public Instance Methods
execute(transport)
click to toggle source
# File lib/uv-rays/http/request.rb, line 105 def execute(transport) # configure ntlm request headers if @options[:ntlm] @options[:headers] ||= {} @options[:headers][:Authorization] ||= ntlm_auth_header end head, body = build_request, @options[:body] @transport = transport @middleware.each do |m| begin head, body = m.request(self, head, body) if m.respond_to?(:request) rescue => e reject e return end end body = body.is_a?(Hash) ? form_encode_body(body) : body file = @options[:file] query = @options[:query] # Set the Content-Length if file is given head['content-length'] = File.size(file) if file # Set the Content-Length if body is given, # or we're doing an empty post or put if body head['content-length'] = body.bytesize elsif method == :post or method == :put # wont happen if body is set and we already set content-length above head['content-length'] ||= 0 end # Set content-type header if missing and body is a Ruby hash if !head['content-type'] and @options[:body].is_a? Hash head['content-type'] = 'application/x-www-form-urlencoded' end request_header = encode_request(method, @path, query) if @http_proxy && (@http_proxy[:username] || @http_proxy[:password]) request_header << encode_auth('Proxy-Authorization', [@http_proxy[:username], @http_proxy[:password]]) end request_header << encode_headers(head) request_header << CRLF if body request_header << body transport.write(request_header).catch &@error elsif file transport.write(request_header).catch &@error # Send file fileRef = @reactor.file file, File::RDONLY do # File is open and available for reading pSend = fileRef.send_file(transport, using: :raw, wait: :promise) pSend.catch &@error pSend.finally do fileRef.close end end fileRef.catch &@error else transport.write(request_header).catch &@error end end
notify(*args)
click to toggle source
# File lib/uv-rays/http/request.rb, line 173 def notify(*args) @defer.notify(*args) end
on_headers(&callback)
click to toggle source
# File lib/uv-rays/http/request.rb, line 181 def on_headers(&callback) @headers_callback = callback end
reject(reason)
click to toggle source
# File lib/uv-rays/http/request.rb, line 101 def reject(reason) @defer.reject(reason) end
resolve(response, parser = nil)
click to toggle source
# File lib/uv-rays/http/request.rb, line 70 def resolve(response, parser = nil) if response.status == 401 && @challenge_retries == 0 && response[:"WWW-Authenticate"] challenge = Array(response[:"WWW-Authenticate"]).reject { |auth| auth.downcase == 'negotiate' }[0] begin if @ntlm_creds && challenge[0..3] == 'NTLM' @options[:headers] ||= {} @options[:headers][:Authorization] = ntlm_auth_header(challenge) @challenge_retries += 1 execute(@transport) return false elsif @digest_creds && challenge[0..5] == 'Digest' @options[:headers] ||= {} @options[:headers][:Authorization] = digest_auth_header(challenge) @challenge_retries += 1 execute(@transport) return false end rescue => e reject e true end end @transport = nil @defer.resolve(response) true end
set_headers(head)
click to toggle source
# File lib/uv-rays/http/request.rb, line 177 def set_headers(head) @headers_callback.call(head) if @headers_callback end
streaming?()
click to toggle source
# File lib/uv-rays/http/request.rb, line 185 def streaming? @options[:streaming] end
Protected Instance Methods
build_request()
click to toggle source
# File lib/uv-rays/http/request.rb, line 193 def build_request head = @options[:headers] ? munge_header_keys(@options[:headers]) : {} # Set the cookie header if provided @cookies = @cookiejar.get(@uri) if cookie = head[COOKIE] @cookies << encode_cookie(cookie) end head[COOKIE] = @cookies.compact.uniq.join("; ").squeeze(";") unless @cookies.empty? # Set connection close unless keep-alive if !@options[:keepalive] head['connection'] = 'close' end # Set the Host header if it hasn't been specified already head['host'] ||= @encoded_host # Set the User-Agent if it hasn't been specified if !head.key?('user-agent') head['user-agent'] = "UV HttpClient" elsif head['user-agent'].nil? head.delete('user-agent') end head end
digest_auth_header(challenge)
click to toggle source
# File lib/uv-rays/http/request.rb, line 250 def digest_auth_header(challenge) uri = URI.parse @uri uri.userinfo = "#{CGI::escape(@digest_creds[:user])}:#{CGI::escape(@digest_creds[:password])}" digest_auth = Net::HTTP::DigestAuth.new auth = digest_auth.auth_header uri, challenge, method.to_s.upcase auth end
ntlm_auth_header(challenge = nil)
click to toggle source
# File lib/uv-rays/http/request.rb, line 221 def ntlm_auth_header(challenge = nil) if @ntlm_auth && challenge.nil? return @ntlm_auth elsif challenge scheme, param_str = parse_ntlm_challenge_header(challenge) if param_str.nil? @ntlm_auth = nil return ntlm_auth_header(@ntlm_creds) else t2 = Net::NTLM::Message.decode64(param_str) t3 = t2.response(@ntlm_creds, ntlmv2: true) @ntlm_auth = "NTLM #{t3.encode64}" return @ntlm_auth end else domain = @ntlm_creds[:domain] t1 = Net::NTLM::Message::Type1.new() t1.domain = domain if domain @ntlm_auth = "NTLM #{t1.encode64}" return @ntlm_auth end end
parse_ntlm_challenge_header(challenge)
click to toggle source
# File lib/uv-rays/http/request.rb, line 244 def parse_ntlm_challenge_header(challenge) scheme, param_str = challenge.scan(/\A(\S+)(?:\s+(.*))?\z/)[0] return nil if scheme.nil? return scheme, param_str end