mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-12-15 00:01:02 -05:00
scoping http auth schemes out of its plugins, made them usable in proxy
In order to expose other auth schemes in proxy, the basic, digest and ntlm modules were extracted from the plugins, these being left with the request management. So now, an extra parameter, `:scheme`, can be passed (it'll be "basic" for http and "socks5" for socks5 by default, can also be "digest" or "ntlm", haven't tested those yet).
This commit is contained in:
parent
e3191f0d6c
commit
817a10a537
@ -152,7 +152,7 @@ Lint/EmptyBlock:
|
||||
Enabled: false # and neither does this. I don't control 3rd party methods.
|
||||
Style/HashTransformValues:
|
||||
Exclude:
|
||||
- 'lib/httpx/plugins/digest_authentication.rb'
|
||||
- 'lib/httpx/plugins/authentication/digest.rb'
|
||||
|
||||
Bundler/DuplicatedGem:
|
||||
Enabled: false
|
||||
|
||||
26
lib/httpx/plugins/authentication/basic.rb
Normal file
26
lib/httpx/plugins/authentication/basic.rb
Normal file
@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "base64"
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Basic
|
||||
def initialize(user, password, *)
|
||||
@user = user
|
||||
@password = password
|
||||
end
|
||||
|
||||
def can_authenticate?(response)
|
||||
!response.is_a?(ErrorResponse) &&
|
||||
response.status == 401 && response.headers.key?("www-authenticate") &&
|
||||
/Basic .*/.match?(response.headers["www-authenticate"])
|
||||
end
|
||||
|
||||
def authenticate(*)
|
||||
"Basic #{Base64.strict_encode64("#{@user}:#{@password}")}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
111
lib/httpx/plugins/authentication/digest.rb
Normal file
111
lib/httpx/plugins/authentication/digest.rb
Normal file
@ -0,0 +1,111 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "time"
|
||||
require "securerandom"
|
||||
require "digest"
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Digest
|
||||
using RegexpExtensions unless Regexp.method_defined?(:match?)
|
||||
|
||||
def initialize(user, password)
|
||||
@user = user
|
||||
@password = password
|
||||
@nonce = 0
|
||||
end
|
||||
|
||||
def can_authenticate?(response)
|
||||
!response.is_a?(ErrorResponse) &&
|
||||
response.status == 401 && response.headers.key?("www-authenticate") &&
|
||||
/Digest .*/.match?(response.headers["www-authenticate"])
|
||||
end
|
||||
|
||||
def authenticate(request, response)
|
||||
"Digest #{generate_header(request, response)}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_header(request, response, iis = false)
|
||||
meth = request.verb.to_s.upcase
|
||||
www = response.headers["www-authenticate"]
|
||||
|
||||
# discard first token, it's Digest
|
||||
auth_info = www[/^(\w+) (.*)/, 2]
|
||||
|
||||
uri = request.path
|
||||
|
||||
params = Hash[auth_info.split(/ *, */)
|
||||
.map { |val| val.split("=") }
|
||||
.map { |k, v| [k, v.delete("\"")] }]
|
||||
nonce = params["nonce"]
|
||||
nc = next_nonce
|
||||
|
||||
# verify qop
|
||||
qop = params["qop"]
|
||||
|
||||
if params["algorithm"] =~ /(.*?)(-sess)?$/
|
||||
alg = Regexp.last_match(1)
|
||||
algorithm = ::Digest.const_get(alg)
|
||||
raise DigestError, "unknown algorithm \"#{alg}\"" unless algorithm
|
||||
|
||||
sess = Regexp.last_match(2)
|
||||
params.delete("algorithm")
|
||||
else
|
||||
algorithm = ::Digest::MD5
|
||||
end
|
||||
|
||||
if qop || sess
|
||||
cnonce = make_cnonce
|
||||
nc = format("%<nonce>08x", nonce: nc)
|
||||
end
|
||||
|
||||
a1 = if sess
|
||||
[algorithm.hexdigest("#{@user}:#{params["realm"]}:#{@password}"),
|
||||
nonce,
|
||||
cnonce].join ":"
|
||||
else
|
||||
"#{@user}:#{params["realm"]}:#{@password}"
|
||||
end
|
||||
|
||||
ha1 = algorithm.hexdigest(a1)
|
||||
ha2 = algorithm.hexdigest("#{meth}:#{uri}")
|
||||
request_digest = [ha1, nonce]
|
||||
request_digest.push(nc, cnonce, qop) if qop
|
||||
request_digest << ha2
|
||||
request_digest = request_digest.join(":")
|
||||
|
||||
header = [
|
||||
%(username="#{@user}"),
|
||||
%(nonce="#{nonce}"),
|
||||
%(uri="#{uri}"),
|
||||
%(response="#{algorithm.hexdigest(request_digest)}"),
|
||||
]
|
||||
header << %(realm="#{params["realm"]}") if params.key?("realm")
|
||||
header << %(algorithm=#{params["algorithm"]}") if params.key?("algorithm")
|
||||
header << %(opaque="#{params["opaque"]}") if params.key?("opaque")
|
||||
header << %(cnonce="#{cnonce}") if cnonce
|
||||
header << %(nc=#{nc})
|
||||
if qop
|
||||
header << iis ? %(qop="#{qop}") : %(qop=#{qop})
|
||||
end
|
||||
header.join ", "
|
||||
end
|
||||
|
||||
def make_cnonce
|
||||
::Digest::MD5.hexdigest [
|
||||
Time.now.to_i,
|
||||
Process.pid,
|
||||
SecureRandom.random_number(2**32),
|
||||
].join ":"
|
||||
end
|
||||
|
||||
def next_nonce
|
||||
@nonce += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
37
lib/httpx/plugins/authentication/ntlm.rb
Normal file
37
lib/httpx/plugins/authentication/ntlm.rb
Normal file
@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "base64"
|
||||
require "ntlm"
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Ntlm
|
||||
def initialize(user, password, domain: nil)
|
||||
@user = user
|
||||
@password = password
|
||||
@domain = domain
|
||||
end
|
||||
|
||||
def can_authenticate?(response)
|
||||
!response.is_a?(ErrorResponse) && response.status == 401 &&
|
||||
response.headers.key?("www-authenticate") &&
|
||||
/NTLM .*/.match?(response.headers["www-authenticate"])
|
||||
end
|
||||
|
||||
def negotiate
|
||||
"NTLM #{NTLM.negotiate(domain: @domain).to_base64}"
|
||||
end
|
||||
|
||||
def authenticate(_, response)
|
||||
challenge = response.headers["www-authenticate"][/NTLM (.*)/, 1]
|
||||
|
||||
challenge = Base64.decode64(challenge)
|
||||
ntlm_challenge = NTLM.authenticate(challenge, @user, @domain, @password).to_base64
|
||||
|
||||
"NTLM #{ntlm_challenge}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
24
lib/httpx/plugins/authentication/socks5.rb
Normal file
24
lib/httpx/plugins/authentication/socks5.rb
Normal file
@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "base64"
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Socks5
|
||||
def initialize(user, password)
|
||||
@user = user
|
||||
@password = password
|
||||
end
|
||||
|
||||
def can_authenticate?(*)
|
||||
@user && @password
|
||||
end
|
||||
|
||||
def authenticate(*)
|
||||
[0x01, @user.bytesize, @user, @password.bytesize, @password].pack("CCA*CA*")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -10,7 +10,7 @@ module HTTPX
|
||||
module BasicAuthentication
|
||||
class << self
|
||||
def load_dependencies(_klass)
|
||||
require "base64"
|
||||
require_relative "authentication/basic"
|
||||
end
|
||||
|
||||
def configure(klass)
|
||||
@ -20,7 +20,7 @@ module HTTPX
|
||||
|
||||
module InstanceMethods
|
||||
def basic_authentication(user, password)
|
||||
authentication("Basic #{Base64.strict_encode64("#{user}:#{password}")}")
|
||||
authentication(Authentication::Basic.new(user, password).authenticate)
|
||||
end
|
||||
alias_method :basic_auth, :basic_authentication
|
||||
end
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "digest"
|
||||
|
||||
module HTTPX
|
||||
module Plugins
|
||||
#
|
||||
@ -10,8 +8,6 @@ module HTTPX
|
||||
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#authentication
|
||||
#
|
||||
module DigestAuthentication
|
||||
using RegexpExtensions unless Regexp.method_defined?(:match?)
|
||||
|
||||
DigestError = Class.new(Error)
|
||||
|
||||
class << self
|
||||
@ -20,14 +16,13 @@ module HTTPX
|
||||
end
|
||||
|
||||
def load_dependencies(*)
|
||||
require "securerandom"
|
||||
require "digest"
|
||||
require_relative "authentication/digest"
|
||||
end
|
||||
end
|
||||
|
||||
module OptionsMethods
|
||||
def option_digest(value)
|
||||
raise TypeError, ":digest must be a Digest" unless value.is_a?(Digest)
|
||||
raise TypeError, ":digest must be a Digest" unless value.is_a?(Authentication::Digest)
|
||||
|
||||
value
|
||||
end
|
||||
@ -35,7 +30,7 @@ module HTTPX
|
||||
|
||||
module InstanceMethods
|
||||
def digest_authentication(user, password)
|
||||
with(digest: Digest.new(user, password))
|
||||
with(digest: Authentication::Digest.new(user, password))
|
||||
end
|
||||
|
||||
alias_method :digest_auth, :digest_authentication
|
||||
@ -44,114 +39,23 @@ module HTTPX
|
||||
requests.flat_map do |request|
|
||||
digest = request.options.digest
|
||||
|
||||
if digest
|
||||
probe_response = wrap { super(request).first }
|
||||
|
||||
if digest && !probe_response.is_a?(ErrorResponse) &&
|
||||
probe_response.status == 401 && probe_response.headers.key?("www-authenticate") &&
|
||||
/Digest .*/.match?(probe_response.headers["www-authenticate"])
|
||||
|
||||
request.transition(:idle)
|
||||
|
||||
token = digest.generate_header(request, probe_response)
|
||||
request.headers["authorization"] = "Digest #{token}"
|
||||
|
||||
super(request)
|
||||
else
|
||||
probe_response
|
||||
end
|
||||
else
|
||||
unless digest
|
||||
super(request)
|
||||
next
|
||||
end
|
||||
|
||||
probe_response = wrap { super(request).first }
|
||||
|
||||
if digest.can_authenticate?(probe_response)
|
||||
request.transition(:idle)
|
||||
request.headers["authorization"] = digest.authenticate(request, probe_response)
|
||||
super(request)
|
||||
else
|
||||
probe_response
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Digest
|
||||
def initialize(user, password)
|
||||
@user = user
|
||||
@password = password
|
||||
@nonce = 0
|
||||
end
|
||||
|
||||
def generate_header(request, response, _iis = false)
|
||||
meth = request.verb.to_s.upcase
|
||||
www = response.headers["www-authenticate"]
|
||||
|
||||
# discard first token, it's Digest
|
||||
auth_info = www[/^(\w+) (.*)/, 2]
|
||||
|
||||
uri = request.path
|
||||
|
||||
params = Hash[auth_info.split(/ *, */)
|
||||
.map { |val| val.split("=") }
|
||||
.map { |k, v| [k, v.delete("\"")] }]
|
||||
nonce = params["nonce"]
|
||||
nc = next_nonce
|
||||
|
||||
# verify qop
|
||||
qop = params["qop"]
|
||||
|
||||
if params["algorithm"] =~ /(.*?)(-sess)?$/
|
||||
alg = Regexp.last_match(1)
|
||||
algorithm = ::Digest.const_get(alg)
|
||||
raise DigestError, "unknown algorithm \"#{alg}\"" unless algorithm
|
||||
|
||||
sess = Regexp.last_match(2)
|
||||
params.delete("algorithm")
|
||||
else
|
||||
algorithm = ::Digest::MD5
|
||||
end
|
||||
|
||||
if qop || sess
|
||||
cnonce = make_cnonce
|
||||
nc = format("%<nonce>08x", nonce: nc)
|
||||
end
|
||||
|
||||
a1 = if sess
|
||||
[algorithm.hexdigest("#{@user}:#{params["realm"]}:#{@password}"),
|
||||
nonce,
|
||||
cnonce].join ":"
|
||||
else
|
||||
"#{@user}:#{params["realm"]}:#{@password}"
|
||||
end
|
||||
|
||||
ha1 = algorithm.hexdigest(a1)
|
||||
ha2 = algorithm.hexdigest("#{meth}:#{uri}")
|
||||
request_digest = [ha1, nonce]
|
||||
request_digest.push(nc, cnonce, qop) if qop
|
||||
request_digest << ha2
|
||||
request_digest = request_digest.join(":")
|
||||
|
||||
header = [
|
||||
%(username="#{@user}"),
|
||||
%(nonce="#{nonce}"),
|
||||
%(uri="#{uri}"),
|
||||
%(response="#{algorithm.hexdigest(request_digest)}"),
|
||||
]
|
||||
header << %(realm="#{params["realm"]}") if params.key?("realm")
|
||||
header << %(algorithm=#{params["algorithm"]}") if params.key?("algorithm")
|
||||
header << %(opaque="#{params["opaque"]}") if params.key?("opaque")
|
||||
header << %(cnonce="#{cnonce}") if cnonce
|
||||
header << %(nc=#{nc})
|
||||
header << %(qop=#{qop}) if qop
|
||||
header.join ", "
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def make_cnonce
|
||||
::Digest::MD5.hexdigest [
|
||||
Time.now.to_i,
|
||||
Process.pid,
|
||||
SecureRandom.random_number(2**32),
|
||||
].join ":"
|
||||
end
|
||||
|
||||
def next_nonce
|
||||
@nonce += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
register_plugin :digest_authentication, DigestAuthentication
|
||||
|
||||
@ -6,12 +6,9 @@ module HTTPX
|
||||
# https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#ntlm-authentication
|
||||
#
|
||||
module NTLMAuthentication
|
||||
NTLMParams = Struct.new(:user, :domain, :password)
|
||||
|
||||
class << self
|
||||
def load_dependencies(_klass)
|
||||
require "base64"
|
||||
require "ntlm"
|
||||
require_relative "authentication/ntlm"
|
||||
end
|
||||
|
||||
def extra_options(options)
|
||||
@ -21,7 +18,7 @@ module HTTPX
|
||||
|
||||
module OptionsMethods
|
||||
def option_ntlm(value)
|
||||
raise TypeError, ":ntlm must be a #{NTLMParams}" unless value.is_a?(NTLMParams)
|
||||
raise TypeError, ":ntlm must be a #{Authentication::Ntlm}" unless value.is_a?(Authentication::Ntlm)
|
||||
|
||||
value
|
||||
end
|
||||
@ -29,7 +26,7 @@ module HTTPX
|
||||
|
||||
module InstanceMethods
|
||||
def ntlm_authentication(user, password, domain = nil)
|
||||
with(ntlm: NTLMParams.new(user, domain, password))
|
||||
with(ntlm: Authentication::Ntlm.new(user, password, domain: domain))
|
||||
end
|
||||
|
||||
alias_method :ntlm_auth, :ntlm_authentication
|
||||
@ -39,19 +36,12 @@ module HTTPX
|
||||
ntlm = request.options.ntlm
|
||||
|
||||
if ntlm
|
||||
request.headers["authorization"] = "NTLM #{NTLM.negotiate(domain: ntlm.domain).to_base64}"
|
||||
request.headers["authorization"] = ntlm.negotiate
|
||||
probe_response = wrap { super(request).first }
|
||||
|
||||
if !probe_response.is_a?(ErrorResponse) && probe_response.status == 401 &&
|
||||
probe_response.headers.key?("www-authenticate") &&
|
||||
(challenge = probe_response.headers["www-authenticate"][/NTLM (.*)/, 1])
|
||||
|
||||
challenge = Base64.decode64(challenge)
|
||||
ntlm_challenge = NTLM.authenticate(challenge, ntlm.user, ntlm.domain, ntlm.password).to_base64
|
||||
|
||||
if ntlm.can_authenticate?(probe_response)
|
||||
request.transition(:idle)
|
||||
|
||||
request.headers["authorization"] = "NTLM #{ntlm_challenge}"
|
||||
request.headers["authorization"] = ntlm.authenticate(request, probe_response)
|
||||
super(request)
|
||||
else
|
||||
probe_response
|
||||
|
||||
@ -19,22 +19,43 @@ module HTTPX
|
||||
PROXY_ERRORS = [TimeoutError, IOError, SystemCallError, Error].freeze
|
||||
|
||||
class Parameters
|
||||
attr_reader :uri, :username, :password
|
||||
attr_reader :uri, :username, :password, :scheme
|
||||
|
||||
def initialize(uri:, username: nil, password: nil)
|
||||
def initialize(uri:, scheme: nil, username: nil, password: nil, **extra)
|
||||
@uri = uri.is_a?(URI::Generic) ? uri : URI(uri)
|
||||
@username = username || @uri.user
|
||||
@password = password || @uri.password
|
||||
|
||||
return unless @username && @password
|
||||
|
||||
scheme ||= case @uri.scheme
|
||||
when "socks5"
|
||||
@uri.scheme
|
||||
when "http", "https"
|
||||
"basic"
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
@scheme = scheme
|
||||
|
||||
auth_scheme = scheme.to_s.capitalize
|
||||
|
||||
require_relative "authentication/#{scheme}" unless defined?(Authentication) && Authentication.const_defined?(auth_scheme)
|
||||
|
||||
@authenticator = Authentication.const_get(auth_scheme).new(@username, @password, **extra)
|
||||
end
|
||||
|
||||
def authenticated?
|
||||
@username && @password
|
||||
def can_authenticate?(*args)
|
||||
return false unless @authenticator
|
||||
|
||||
@authenticator.can_authenticate?(*args)
|
||||
end
|
||||
|
||||
def token_authentication
|
||||
return unless authenticated?
|
||||
def authenticate(*args)
|
||||
return unless @authenticator
|
||||
|
||||
Base64.strict_encode64("#{@username}:#{@password}")
|
||||
@authenticator.authenticate(*args)
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
@ -42,7 +63,8 @@ module HTTPX
|
||||
when Parameters
|
||||
@uri == other.uri &&
|
||||
@username == other.username &&
|
||||
@password == other.password
|
||||
@password == other.password &&
|
||||
@scheme == other.scheme
|
||||
when URI::Generic, String
|
||||
proxy_uri = @uri.dup
|
||||
proxy_uri.user = @username
|
||||
|
||||
@ -59,7 +59,7 @@ module HTTPX
|
||||
end
|
||||
end
|
||||
|
||||
def __http_on_connect(_, response)
|
||||
def __http_on_connect(request, response)
|
||||
@inflight -= 1
|
||||
if response.status == 200
|
||||
req = @pending.first
|
||||
@ -67,6 +67,11 @@ module HTTPX
|
||||
@io = ProxySSL.new(@io, request_uri, @options)
|
||||
transition(:connected)
|
||||
throw(:called)
|
||||
elsif @options.proxy.can_authenticate?(response)
|
||||
request.transition(:idle)
|
||||
request.headers["proxy-authorization"] = @options.proxy.authenticate(request, response)
|
||||
@inflight += 1
|
||||
parser.send(connect_request)
|
||||
else
|
||||
pending = @pending + @parser.pending
|
||||
while (req = pending.shift)
|
||||
@ -88,7 +93,10 @@ module HTTPX
|
||||
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
|
||||
|
||||
@ -18,6 +18,10 @@ module HTTPX
|
||||
|
||||
Error = Socks5Error
|
||||
|
||||
def self.load_dependencies(*)
|
||||
require_relative "../authentication/socks5"
|
||||
end
|
||||
|
||||
module ConnectionMethods
|
||||
def call
|
||||
super
|
||||
@ -156,16 +160,14 @@ module HTTPX
|
||||
|
||||
def negotiate(parameters)
|
||||
methods = [NOAUTH]
|
||||
methods << PASSWD if parameters.authenticated?
|
||||
methods << PASSWD if parameters.can_authenticate?
|
||||
methods.unshift(methods.size)
|
||||
methods.unshift(VERSION)
|
||||
methods.pack("C*")
|
||||
end
|
||||
|
||||
def authenticate(parameters)
|
||||
user = parameters.username
|
||||
password = parameters.password
|
||||
[0x01, user.bytesize, user, password.bytesize, password].pack("CCA*CA*")
|
||||
parameters.authenticate
|
||||
end
|
||||
|
||||
def connect(uri)
|
||||
|
||||
19
sig/plugins/authentication/basic.rbs
Normal file
19
sig/plugins/authentication/basic.rbs
Normal file
@ -0,0 +1,19 @@
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Basic
|
||||
@user: String
|
||||
@password: String
|
||||
|
||||
def can_authenticate?: (response) -> boolish
|
||||
|
||||
def authenticate: (*untyped) -> String
|
||||
|
||||
private
|
||||
|
||||
def initialize: (string user, string password, *untyped) -> void
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
24
sig/plugins/authentication/digest.rbs
Normal file
24
sig/plugins/authentication/digest.rbs
Normal file
@ -0,0 +1,24 @@
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Digest
|
||||
@user: String
|
||||
@password: String
|
||||
|
||||
def can_authenticate?: (response) -> boolish
|
||||
|
||||
def authenticate: (Request request, Response response) -> String
|
||||
|
||||
private
|
||||
|
||||
def generate_header: (Request request, Response response, ?bool? iis) -> String
|
||||
|
||||
def initialize: (string user, string password) -> void
|
||||
|
||||
def make_cnonce: () -> String
|
||||
|
||||
def next_nonce: () -> Integer
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
sig/plugins/authentication/ntlm.rbs
Normal file
20
sig/plugins/authentication/ntlm.rbs
Normal file
@ -0,0 +1,20 @@
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Ntlm
|
||||
@user: String
|
||||
@password: String
|
||||
@domain: String?
|
||||
|
||||
def can_authenticate?: (response) -> boolish
|
||||
|
||||
def authenticate: (*untyped) -> String
|
||||
|
||||
private
|
||||
|
||||
def initialize: (string user, string password, ?domain: String?) -> void
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
18
sig/plugins/authentication/socks5.rbs
Normal file
18
sig/plugins/authentication/socks5.rbs
Normal file
@ -0,0 +1,18 @@
|
||||
module HTTPX
|
||||
module Plugins
|
||||
module Authentication
|
||||
class Socks5
|
||||
@user: String
|
||||
@password: String
|
||||
|
||||
def can_authenticate?: (*untyped) -> boolish
|
||||
|
||||
def authenticate: (*untyped) -> String
|
||||
|
||||
private
|
||||
|
||||
def initialize: (string user, string password) -> void
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -4,7 +4,7 @@ module HTTPX
|
||||
DigestError: singleton(Error)
|
||||
|
||||
interface _DigestOptions
|
||||
def digest: () -> Digest?
|
||||
def digest: () -> Authentication::Digest?
|
||||
end
|
||||
|
||||
def self.extra_options: (Options) -> (Options & _DigestOptions)
|
||||
@ -14,16 +14,6 @@ module HTTPX
|
||||
module InstanceMethods
|
||||
def digest_authentication: (string user, string password) -> instance
|
||||
end
|
||||
|
||||
class Digest
|
||||
def generate_header: (Request, Response, ?bool?) -> String
|
||||
|
||||
private
|
||||
|
||||
def initialize: (string user, string password) -> untyped
|
||||
def make_cnonce: () -> String
|
||||
def next_nonce: () -> Integer
|
||||
end
|
||||
end
|
||||
|
||||
type sessionDigestAuthentication = sessionAuthentication & DigestAuthentication::InstanceMethods
|
||||
|
||||
@ -3,7 +3,7 @@ module HTTPX
|
||||
module NTLMAuthentication
|
||||
|
||||
interface _NTLMOptions
|
||||
def ntlm: () -> NTLMParams?
|
||||
def ntlm: () -> Authentication::Ntlm?
|
||||
end
|
||||
|
||||
def self.extra_options: (Options) -> (Options & _NTLMOptions)
|
||||
@ -14,11 +14,6 @@ module HTTPX
|
||||
def ntlm_authentication: (string user, string password, ?string? domain) -> instance
|
||||
end
|
||||
|
||||
class NTLMParams
|
||||
attr_reader user: String
|
||||
attr_reader password: String
|
||||
attr_reader domain: String?
|
||||
end
|
||||
end
|
||||
|
||||
type sessionNTLMAuthentication = sessionAuthentication & NTLMAuthentication::InstanceMethods
|
||||
|
||||
@ -11,15 +11,17 @@ module HTTPX
|
||||
attr_reader uri: URI::Generic
|
||||
attr_reader username: String?
|
||||
attr_reader password: String?
|
||||
attr_reader scheme: String?
|
||||
|
||||
def authenticated?: () -> boolish
|
||||
def token_authentication: () -> String?
|
||||
def can_authenticate?: (*untyped) -> boolish
|
||||
|
||||
def authenticate: (*untyped) -> String?
|
||||
|
||||
def ==: (untyped) -> bool
|
||||
|
||||
private
|
||||
|
||||
def initialize: (uri: generic_uri, ?username: String, ?password: String) -> untyped
|
||||
def initialize: (uri: generic_uri, ?scheme: String, ?username: String, ?password: String, **extra) -> untyped
|
||||
end
|
||||
|
||||
def self.configure: (singleton(Session)) -> void
|
||||
|
||||
@ -6,7 +6,7 @@ require "httpx/plugins/proxy"
|
||||
class ProxyTest < Minitest::Test
|
||||
include HTTPX
|
||||
|
||||
def test_parameters
|
||||
def test_parameters_equality
|
||||
params = parameters(username: "user", password: "pass")
|
||||
assert params == parameters(username: "user", password: "pass")
|
||||
assert params != parameters(username: "user2", password: "pass")
|
||||
@ -17,17 +17,6 @@ class ProxyTest < Minitest::Test
|
||||
assert params != 1
|
||||
end
|
||||
|
||||
def test_parameters_authenticated
|
||||
assert parameters(username: "user", password: "pass").authenticated?
|
||||
assert !parameters.authenticated?
|
||||
end
|
||||
|
||||
def test_parameters_token_authentication
|
||||
params = parameters(username: "user", password: "pass")
|
||||
assert params.token_authentication == Base64.strict_encode64("user:pass"),
|
||||
"it should have base64-rencoded the credentials"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parameters(uri: "http://proxy", **args)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user