Golang ServeHTTP 在 POST 请求上使代理错误 EOF
Golang ServeHTTP make proxy error EOF on POST request
我正在使用 gin 和 ServeHTTP 开发代理服务器。实际上 GET 和 OPTIONS 请求效果很好。但是当我尝试多个 POST 请求时,我在两个请求中得到一个 EOF 错误。
我已经测试过 没有代理服务的重复请求及其工作 很好,所以我的代码中有些东西不起作用。
编辑:
- 我用 https://ptsv2.com/ 测试了 POST 代理,所有请求响应 return 200 状态码。
// main.go
package main
import (
"fmt"
"../pkg/api"
)
func main() {
fmt.Println("Starting server")
api.InitServer()
}
// routes.go
package api
import (
"github.com/gin-gonic/gin"
)
const serviceUrl = "http://localhost:8732"
func InitServer() {
router := gin.Default()
defineRoutes(router)
router.Run()
}
func defineRoutes(router *gin.Engine) {
router.GET("/ping", Ping)
router.POST("/*any", Proxy(serviceUrl))
}
// controller.go
package api
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"github.com/gin-gonic/gin"
)
type transport struct {
http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
resp, err = t.RoundTripper.RoundTrip(req)
if err != nil {
// EOF ERROR HERE
return nil, err
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = resp.Body.Close()
if err != nil {
return nil, err
}
b = bytes.Replace(b, []byte("server"), []byte("schmerver"), -1)
body := ioutil.NopCloser(bytes.NewReader(b))
response := resp
response.Body = body
response.ContentLength = int64(len(b))
response.Header.Set("Content-Length", strconv.Itoa(len(b)))
response.Header.Set("Access-Control-Allow-Origin", "*")
return response, nil
}
func Proxy(targetUrl string) gin.HandlerFunc {
fn := func(c *gin.Context) {
remote, err := url.Parse(targetUrl)
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.Director = func(req *http.Request) {
req.Header = c.Request.Header
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.Close = true // True / False same result
}
proxy.Transport = &transport{http.DefaultTransport}
proxy.ServeHTTP(c.Writer, c.Request)
}
return fn
}
结论
你的代码没有错误。有用。可能是你的网络设置不对。
解释一下
我下载了您的代码并使用本地后端服务器对其进行了测试。有效。
附录
后端服务器代码
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
fmt.Println("Starting server")
router := gin.Default()
router.POST("/*any", func(c *gin.Context) {
c.JSON(200, gin.H{
"mes": "hello",
})
})
router.Run(":8888")
}
我正在使用 gin 和 ServeHTTP 开发代理服务器。实际上 GET 和 OPTIONS 请求效果很好。但是当我尝试多个 POST 请求时,我在两个请求中得到一个 EOF 错误。 我已经测试过 没有代理服务的重复请求及其工作 很好,所以我的代码中有些东西不起作用。
编辑:
- 我用 https://ptsv2.com/ 测试了 POST 代理,所有请求响应 return 200 状态码。
// main.go
package main
import (
"fmt"
"../pkg/api"
)
func main() {
fmt.Println("Starting server")
api.InitServer()
}
// routes.go
package api
import (
"github.com/gin-gonic/gin"
)
const serviceUrl = "http://localhost:8732"
func InitServer() {
router := gin.Default()
defineRoutes(router)
router.Run()
}
func defineRoutes(router *gin.Engine) {
router.GET("/ping", Ping)
router.POST("/*any", Proxy(serviceUrl))
}
// controller.go
package api
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"github.com/gin-gonic/gin"
)
type transport struct {
http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
resp, err = t.RoundTripper.RoundTrip(req)
if err != nil {
// EOF ERROR HERE
return nil, err
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = resp.Body.Close()
if err != nil {
return nil, err
}
b = bytes.Replace(b, []byte("server"), []byte("schmerver"), -1)
body := ioutil.NopCloser(bytes.NewReader(b))
response := resp
response.Body = body
response.ContentLength = int64(len(b))
response.Header.Set("Content-Length", strconv.Itoa(len(b)))
response.Header.Set("Access-Control-Allow-Origin", "*")
return response, nil
}
func Proxy(targetUrl string) gin.HandlerFunc {
fn := func(c *gin.Context) {
remote, err := url.Parse(targetUrl)
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
proxy.Director = func(req *http.Request) {
req.Header = c.Request.Header
req.Host = remote.Host
req.URL.Scheme = remote.Scheme
req.URL.Host = remote.Host
req.Close = true // True / False same result
}
proxy.Transport = &transport{http.DefaultTransport}
proxy.ServeHTTP(c.Writer, c.Request)
}
return fn
}
结论
你的代码没有错误。有用。可能是你的网络设置不对。
解释一下
我下载了您的代码并使用本地后端服务器对其进行了测试。有效。
附录
后端服务器代码
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
fmt.Println("Starting server")
router := gin.Default()
router.POST("/*any", func(c *gin.Context) {
c.JSON(200, gin.H{
"mes": "hello",
})
})
router.Run(":8888")
}