diff --git a/CHANGELOG.md b/CHANGELOG.md index 5758593..4c34260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.8.1 + +* Small refactoring ## 0.8.0 * Require Crystal >= 0.36.0 diff --git a/shard.yml b/shard.yml index f1aca94..aed5537 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: http_proxy -version: 0.8.0 +version: 0.8.1 authors: - Theo Li diff --git a/src/ext/http/client.cr b/src/ext/http/client.cr new file mode 100644 index 0000000..ba95641 --- /dev/null +++ b/src/ext/http/client.cr @@ -0,0 +1,60 @@ +require "http" + +module HTTP + class Client + getter proxy : Bool = false + + def set_proxy(proxy : HTTP::Proxy::Client?) + return unless proxy + + begin + @io = proxy.open( + host: @host, + port: @port, + tls: @tls, + dns_timeout: @dns_timeout, + connect_timeout: @connect_timeout, + read_timeout: @read_timeout + ) + rescue ex : IO::Error + raise IO::Error.new("Failed to open TCP connection to #{@host}:#{@port} (#{ex.message})") + end + + @proxy = true + + if proxy.username && proxy.password + proxy_basic_auth(proxy.username, proxy.password) + end + end + + # True if requests for this connection will be proxied + def proxy? + @proxy + end + + private def new_request(method, path, headers, body : BodyType) + # Use full URL instead of path when using HTTP proxy + if proxy? && !@tls + path = "http://#{host_with_port}#{path}" + end + + HTTP::Request.new(method, path, headers, body) + end + + private def host_with_port + host = @host + host = "[#{host}]" if host.includes?(":") + default_port = @tls ? URI.default_port("https") : URI.default_port("http") + default_port == @port ? host : "#{host}:#{@port}" + end + + # Configures this client to perform proxy basic authentication in every + # request. + private def proxy_basic_auth(username : String?, password : String?) + header = "Basic #{Base64.strict_encode("#{username}:#{password}")}" + before_request do |request| + request.headers["Proxy-Authorization"] = header + end + end + end +end