valyala / fasthttp

Fast HTTP package for Go. Tuned for high performance. Zero memory allocations in hot paths. Up to 10x faster than net/http
MIT License
21.66k stars 1.75k forks source link

Using System IPv6 #1578

Closed DenScre closed 1 year ago

DenScre commented 1 year ago

Hello. I tried to transfer the implementation from net/http, but there was a problem, can you tell me how to correctly use ipv6 (system) to create requests.

In this case, if you replace Dial with 'Dial: fasthttpproxy.FasthttpHTTPDialerTimeout("127.0.0.1:3128", time.Second*10),', everything will work. (proxy that leads to '2001:DB8::9')

addr, err := net.ResolveTCPAddr("tcp", "[2001:DB8::9]:0")
if err!=nil{return}

client = &fasthttp.Client{
 Dial: (&fasthttp.TCPDialer{
  LocalAddr: addr,
 }).Dial,
//Dial: fasthttpproxy.FasthttpHTTPDialerTimeout("127.0.0.1:3128", time.Second*10),
DialDualStack: true,
}

req := fasthttp.AcquireRequest()
req.SetRequestURI("https://ifconfig.co/ip")
req.Header.SetMethod(fasthttp.MethodGet)
resp := fasthttp.AcquireResponse()
errs := client.Do(req, resp)

fmt.Printf("Error: %s\n", errs)

fasthttp.ReleaseRequest(req)
respBody := resp.Body()
fmt.Printf("Response: %s\n", respBody)
fasthttp.ReleaseResponse(resp)

Displays an error (current ipv6 for example)

Error: dial tcp4: address [2001:DB8::9]:0: no suitable address found
Response: 
erikdubbelboer commented 1 year ago

I'm afraid that this is currently not possible. FasthttpHTTPDialerTimeout uses fasthttp.Dial which always dials with DualStack disabled. Replacing it with DialDualStack should work. You could try copying fasthttpproxy/http.go into your own project and use this method instead. Let me know if that works and I'll change it in fasthttp as well.

Pluto-zZ-zZ commented 1 year ago

I had the same problem,error : couldn't find DNS entries for the given domain. Try using DialDualStack 56a328ec-0871-44fa-a8fd-e33f1e439427 But I found a way to support it, so I copied and replaced it myself, and it worked 1c090aec-e33b-43b7-b82b-ce73972c6877 065ed1c3-d4ca-457e-bc9b-ec7940a4fbce

Pluto-zZ-zZ commented 1 year ago
func FasthttpHTTPDialerTimeoutWithIpv6(proxy string, timeout time.Duration) fasthttp.DialFunc {
    var auth string
    if strings.Contains(proxy, "@") {
        index := strings.LastIndex(proxy, "@")
        auth = base64.StdEncoding.EncodeToString([]byte(proxy[:index]))
        proxy = proxy[index+1:]
    }

    return func(addr string) (net.Conn, error) {
        var conn net.Conn
        var err error
        if timeout == 0 {
            conn, err = fasthttp.DialDualStack(proxy)
        } else {
            conn, err = fasthttp.DialDualStackTimeout(proxy, timeout)
        }
        if err != nil {
            return nil, err
        }

        req := "CONNECT " + addr + " HTTP/1.1\r\nHost: " + addr + "\r\n"
        if auth != "" {
            req += "Proxy-Authorization: Basic " + auth + "\r\n"
        }
        req += "\r\n"

        if _, err := conn.Write([]byte(req)); err != nil {
            return nil, err
        }

        res := fasthttp.AcquireResponse()
        defer fasthttp.ReleaseResponse(res)

        res.SkipBody = true

        if err := res.Read(bufio.NewReader(conn)); err != nil {
            conn.Close()
            return nil, err
        }
        if res.Header.StatusCode() != 200 {
            conn.Close()
            return nil, fmt.Errorf("could not connect to proxy: %s status code: %d", proxy, res.Header.StatusCode())
        }
        return conn, nil
    }
}
Pluto-zZ-zZ commented 1 year ago
func FasthttpHTTPDialerTimeoutWithIpv6(proxy string, timeout time.Duration) fasthttp.DialFunc {
  var auth string
  if strings.Contains(proxy, "@") {
      index := strings.LastIndex(proxy, "@")
      auth = base64.StdEncoding.EncodeToString([]byte(proxy[:index]))
      proxy = proxy[index+1:]
  }

  return func(addr string) (net.Conn, error) {
      var conn net.Conn
      var err error
      if timeout == 0 {
          conn, err = fasthttp.DialDualStack(proxy)
      } else {
          conn, err = fasthttp.DialDualStackTimeout(proxy, timeout)
      }
      if err != nil {
          return nil, err
      }

      req := "CONNECT " + addr + " HTTP/1.1\r\nHost: " + addr + "\r\n"
      if auth != "" {
          req += "Proxy-Authorization: Basic " + auth + "\r\n"
      }
      req += "\r\n"

      if _, err := conn.Write([]byte(req)); err != nil {
          return nil, err
      }

      res := fasthttp.AcquireResponse()
      defer fasthttp.ReleaseResponse(res)

      res.SkipBody = true

      if err := res.Read(bufio.NewReader(conn)); err != nil {
          conn.Close()
          return nil, err
      }
      if res.Header.StatusCode() != 200 {
          conn.Close()
          return nil, fmt.Errorf("could not connect to proxy: %s status code: %d", proxy, res.Header.StatusCode())
      }
      return conn, nil
  }
}

It's ok for fasthttpproxy use ipv6, and mr : https://github.com/valyala/fasthttp/pull/1597

erikdubbelboer commented 1 year ago

https://github.com/valyala/fasthttp/pull/1597 was merged.