elixir-mint / mint

Functional HTTP client for Elixir with support for HTTP/1 and HTTP/2 🌱
Apache License 2.0
1.36k stars 110 forks source link

HTTP_PROXY doesn't set host for a connection, using proxy as host #446

Open joshuataylor opened 1 month ago

joshuataylor commented 1 month ago

Reading: https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-proxying

A minimal example, using mitmproxy:

proxy_details = {:http, "127.0.0.1", 9055, []}
{:ok, conn} = Mint.HTTP.connect(:http, "example.com", 80, proxy: proxy_details)
{:ok, conn, request_ref} = Mint.HTTP.request(conn, "GET", "/", [], nil)

The raw request seems to be:

GET / HTTP/1.1
host: 127.0.0.1:9055
user-agent: mint/1.5.1

When using hackney, this seems to work:

# Set up the proxy options
proxy_opts = [
  proxy: {"127.0.0.1", 9055}
]

# Make the request using hackney
:hackney.request(:get, "http://example.com", [], "", proxy_opts)

Request:

GET / HTTP/1.1
Host: example.com
User-Agent: hackney/1.20.1

(HTTPoison also works, HTTPoison.get("http://example.com", [], [{:proxy, string_url()}]))

Mint.UnsafeProxy:

conn: %Mint.UnsafeProxy{
  hostname: "example.com",
  port: 80,
  scheme: :http,
  module: Mint.HTTP1,
  proxy_headers: [],
  state: %Mint.HTTP1{
    host: "127.0.0.1",
    port: 9055,
    request: nil,
    streaming_request: nil,
    socket: #Port<0.4>,
    transport: Mint.Core.Transport.TCP,
    mode: :active,
    scheme_as_string: "http",
    requests: {[], []},
    state: :open,
    buffer: "",
    proxy_headers: [],
    private: %{},
    log: false
  }
}
request: %Mint.UnsafeProxy{
  hostname: "example.com",
  port: 80,
  scheme: :http,
  module: Mint.HTTP1,
  proxy_headers: [],
  state: %Mint.HTTP1{
    host: "127.0.0.1",
    port: 9055,
    request: %{
      status: nil,
      version: nil,
      state: :status,
      connection: [],
      body: nil,
      ref: #Reference<0.1840951877.600834051.12099>,
      method: "GET",
      data_buffer: [],
      headers_buffer: [],
      content_length: nil,
      transfer_encoding: []
    },
    streaming_request: nil,
    socket: #Port<0.4>,
    transport: Mint.Core.Transport.TCP,
    mode: :active,
    scheme_as_string: "http",
    requests: {[], []},
    state: :open,
    buffer: "",
    proxy_headers: [],
    private: %{},
    log: false
  }
}
whatyouhide commented 1 month ago

Yeah this seems to be a bug from a super quick look. Wanna give a try to coming up with a patch? 🙃

joshuataylor commented 1 month ago

I guess calling it "preserve host header"/"keep host header" or something would make sense.

Prior art: https://docs.mitmproxy.org/stable/concepts-options/#keep_host_header