英文:
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
这里有几个问题:
- 你的两个
io.Copy()
调用方向是一样的。你需要在其中一个中反转src
和dst
。 - 你的curl命令行使用的是HTTPS,但你的代码只是普通的HTTP。
- 你的curl请求只是请求根目录,这将调用文件服务器,可能只会返回类似"文件未找到"的内容。尝试使用以下curl命令行:
$ curl http://localhost:1111/hello
英文:
There are a few things here:
- Both your
io.Copy()
calls are in the same direction. You need to reversesrc
anddst
in one of them. - Your curl command line is using HTTPS but you code is just plain HTTP.
- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论