本地主机在使用Golang代理时超时

huangapple go评论92阅读模式
英文:

localhost times out when using golang proxy

问题

我正在尝试在Ubuntu 20.04.5上运行一个我用GO编写的简单代理和Web应用程序。Web应用程序(http://localhost:8000)在浏览器上可以正常工作,但是当我将其与代理端口(https://localhost:1111)绑定时,localhost会一直加载直到超时并失败。代理代码编译没有错误,并且能够绑定到正确的端口。

我已经尝试更改两者的端口,但仍然得到相同的结果。

这是代理代码goproxy.go:

package main

import (
    "io"
    "log"
    "net"
)

func main() {
    //监听代理请求
    listener, err := net.Listen("tcp", ":1111")
    if err != nil {
        log.Fatalln("无法绑定端口")
    } else {
        log.Printf("绑定端口")
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Fatalln("无法接受连接")
        } else {
            log.Printf("接受连接")
        }
        //处理代理请求
        go handleConn(conn)
    }
}

func handleConn(src net.Conn) {
    //连接到服务器
    dst, err := net.Dial("tcp", "localhost:8000")
    if err != nil {
        log.Fatalln("无法连接到服务器")
    } else {
        log.Printf("连接到目标服务器")
    }

    defer dst.Close()

    //将src的输出复制到dst连接
    go func() {
        if _, err := io.Copy(dst, src); err != nil {
            log.Fatalln(err)
        } else {
            log.Printf("将src的输出复制到dst连接")
        }
    }()
    //使用目标服务器连接的响应作为src连接的响应
    if _, err := io.Copy(dst, src); err != nil {
        log.Fatalln(err)
    } else {
        log.Printf("使用目标服务器连接的响应")
    }
}

Web服务器代码goserver.go:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func formHandler(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        fmt.Fprintf(w, "ParseForm() 错误: %v", err)
        return
    }
    fmt.Fprintf(w, "POST 请求成功\n")
    name := r.FormValue("name")
    address := r.FormValue("address")
    fmt.Fprintf(w, "姓名 = %s\n", name)
    fmt.Fprintf(w, "地址 = %s\n", address)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/hello" {
        http.Error(w, "404 页面未找到", http.StatusFound)
        return
    }
    if r.Method != "GET" {
        http.Error(w, "不支持的请求方法", http.StatusNotFound)
        return
    }
    fmt.Fprintf(w, "你好!")
}

func main() {
    fileServer := http.FileServer(http.Dir("./static"))
    http.Handle("/", fileServer)
    http.HandleFunc("/form", formHandler)
    http.HandleFunc("/hello", helloHandler)

    fmt.Printf("在端口 8000 上启动服务器\n")
    if err := http.ListenAndServe(":8000", nil); err != nil {
        log.Fatal(err)
    }
}

使用HTTPS localhost运行cURL命令:

cmps401@WINDOWS-HLFMIEE:~/goprogram$ curl -v https://localhost:1111
* 正在尝试连接 127.0.0.1:1111...
* 设置 TCP_NODELAY
* 已连接到 localhost (127.0.0.1) 端口 1111 (#0)
* ALPN, 提供 h2
* ALPN, 提供 http/1.1
* 成功设置证书验证位置:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS 握手, 客户端 hello (1):

如果对此有任何帮助,我会非常感激,这也是我第一个GO程序。如果需要提供更多信息,请告诉我。

英文:

I am trying to run a simple proxy and web app I made with GO on Ubuntu 20.04.5 and the web app (http://localhost:8000) will work on the browser however when I bind it with the proxy port (https://localhost:1111) localhost will load until it times out and fails. The proxy code compiles with no errors and is able to bind onto the correct port.

I have tried changing the ports for both and still get the same result.

Here is the proxy code goproxy.go :

package main
import (
"io"
"log"
"net"
)
func main(){ 
//listen for proxy requests
listener, err := net.Listen("tcp", ":1111")
if err != nil { 
log.Fatalln("unable to bind on port ")
} else { 
log.Printf("binded on port")
}
for 
{
conn, err := listener.Accept()
if err != nil { 
log.Fatalln("unable to accept connection ")
} else {
log.Printf("accepted connection")
}
//handling proxy request
go handleConn(conn)
}
}
func handleConn(src net.Conn) { 
//connect to the server
dst, err := net.Dial("tcp", "localhost:8000")
if err != nil { 
log.Fatalln("unable to target server ")
} else {
log.Printf("connected to target server")
}
defer dst.Close()
//copy the src output to the dst. connection
go func() { 
if _,err := io.Copy(dst, src); err != nil { 
log.Fatalln(err)
} else {
log.Printf("copied src output to the dst conn")
}
}()
//use the respone for target serve connection to src connection
if _,err := io.Copy(dst, src); err != nil { 
log.Fatalln(err)
}else {
log.Printf("using the response for target server connection")
}
}

Web server code goserver.go :

package main
import (
"fmt"
"log"
"net/http"
)
func formHandler(w http.ResponseWriter, r *http.Request) { 
if err := r.ParseForm(); err != nil { 
fmt.Fprintf(w, "ParseForm() err: %v", err)
return
}
fmt.Fprintf(w, "POST request is successful\n")
name := r.FormValue("name")
address := r.FormValue("address")
fmt.Fprintf(w, "Name = %s\n", name)
fmt.Fprintf(w, "Address = %s\n", address)
}
func helloHandler(w http.ResponseWriter, r *http.Request) { 
if r.URL.Path !="/hello"{ 
http.Error(w, "404 not found", http.StatusFound)
return
}
if r.Method != "GET" { 
http.Error(w, "method is not supported", http.StatusNotFound)
return
}
fmt.Fprintf(w,"hello!")
}
func main(){ 
fileServer := http.FileServer(http.Dir("./static"))
http.Handle("/", fileServer)
http.HandleFunc("/form", formHandler)
http.HandleFunc("/hello", helloHandler)
fmt.Printf("Starting server at port 8000\n")
if err := http.ListenAndServe(":8000",nil); err !=nil {
log.Fatal(err)
}
}

Running the cURL command with the HTTPS localhost

cmps401@WINDOWS-HLFMIEE:~/goprogram$ curl -v https://localhost:1111
*   Trying 127.0.0.1:1111...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 1111 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):

Any help with this is appreciated and this is also my first GO program. let me know if I need to provide any more info.

答案1

得分: 1

这里有几个问题:

  1. 你的两个io.Copy()调用方向是一样的。你需要在其中一个中反转srcdst
  2. 你的curl命令行使用的是HTTPS,但你的代码只是普通的HTTP。
  3. 你的curl请求只是请求根目录,这将调用文件服务器,可能只会返回类似"文件未找到"的内容。尝试使用以下curl命令行:
$ curl http://localhost:1111/hello
英文:

There are a few things here:

  1. Both your io.Copy() calls are in the same direction. You need to reverse src and dst in one of them.
  2. Your curl command line is using HTTPS but you code is just plain HTTP.
  3. Your curl request is just asking for the root which will invoke file server and probably just return something like "file not found". Try this curl command line:
$ curl http://localhost:1111/hello

huangapple
  • 本文由 发表于 2022年10月20日 08:19:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/74133187.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定