lib/httpx/plugins/proxy/http.rb in httpx-0.19.8 vs lib/httpx/plugins/proxy/http.rb in httpx-0.20.0

- old
+ new

@@ -4,10 +4,46 @@ module HTTPX module Plugins module Proxy module HTTP + module InstanceMethods + def with_proxy_basic_auth(opts) + with(proxy: opts.merge(scheme: "basic")) + end + + def with_proxy_digest_auth(opts) + with(proxy: opts.merge(scheme: "digest")) + end + + def with_proxy_ntlm_auth(opts) + with(proxy: opts.merge(scheme: "ntlm")) + end + + def fetch_response(request, connections, options) + response = super + + if response && + response.status == 407 && + !request.headers.key?("proxy-authorization") && + response.headers.key?("proxy-authenticate") + + connection = find_connection(request, connections, options) + + if connection.options.proxy.can_authenticate?(response.headers["proxy-authenticate"]) + request.transition(:idle) + request.headers["proxy-authorization"] = + connection.options.proxy.authenticate(request, response.headers["proxy-authenticate"]) + connection.send(request) + return + end + end + + response + end + end + module ConnectionMethods def connecting? super || @state == :connecting || @state == :connected end @@ -21,15 +57,31 @@ return unless @state == :idle @io.connect return unless @io.connected? - @parser = registry(@io.protocol).new(@write_buffer, @options.merge(max_concurrent_requests: 1)) - @parser.extend(ProxyParser) - @parser.once(:response, &method(:__http_on_connect)) - @parser.on(:close) { transition(:closing) } - __http_proxy_connect + @parser || begin + @parser = registry(@io.protocol).new(@write_buffer, @options.merge(max_concurrent_requests: 1)) + parser = @parser + parser.extend(ProxyParser) + parser.on(:response, &method(:__http_on_connect)) + parser.on(:close) { transition(:closing) } + parser.on(:reset) do + if parser.empty? + reset + else + transition(:closing) + transition(:closed) + emit(:reset) + + parser.reset if @parser + transition(:idle) + transition(:connecting) + end + end + __http_proxy_connect(parser) + end return if @state == :connected when :connected return unless @state == :idle || @state == :connecting case @state @@ -42,33 +94,41 @@ end end super end - def __http_proxy_connect + def __http_proxy_connect(parser) req = @pending.first - # if the first request after CONNECT is to an https address, it is assumed that - # all requests in the queue are not only ALL HTTPS, but they also share the certificate, - # and therefore, will share the connection. - # - if req.uri.scheme == "https" + if req && req.uri.scheme == "https" + # if the first request after CONNECT is to an https address, it is assumed that + # all requests in the queue are not only ALL HTTPS, but they also share the certificate, + # and therefore, will share the connection. + # connect_request = ConnectRequest.new(req.uri, @options) @inflight += 1 parser.send(connect_request) else handle_transition(:connected) end end - def __http_on_connect(_, response) + def __http_on_connect(request, response) @inflight -= 1 if response.status == 200 req = @pending.first request_uri = req.uri @io = ProxySSL.new(@io, request_uri, @options) transition(:connected) throw(:called) + elsif response.status == 407 && + !request.headers.key?("proxy-authorization") && + @options.proxy.can_authenticate?(response.headers["proxy-authenticate"]) + + request.transition(:idle) + request.headers["proxy-authorization"] = @options.proxy.authenticate(request, response.headers["proxy-authenticate"]) + @parser.send(request) + @inflight += 1 else pending = @pending + @parser.pending while (req = pending.shift) req.emit(:response, response) end @@ -86,10 +146,13 @@ def set_protocol_headers(request) extra_headers = super proxy_params = @options.proxy - extra_headers["proxy-authorization"] = "Basic #{proxy_params.token_authentication}" if proxy_params.authenticated? + if proxy_params.scheme == "basic" + # opt for basic auth + extra_headers["proxy-authorization"] = proxy_params.authenticate(extra_headers) + end extra_headers["proxy-connection"] = extra_headers.delete("connection") if extra_headers.key?("connection") extra_headers end end