Authentication 具有自定义身份验证的Golang反向代理

Authentication 具有自定义身份验证的Golang反向代理,authentication,go,reverse-proxy,middleware,Authentication,Go,Reverse Proxy,Middleware,在将请求代理到远程服务器之前,我试图通过调用RESTAPI对用户进行身份验证。 但是,我发现如果我在代理到远程服务器之前调用api,请求将失败,并出现以下错误: http: proxy error: http: ContentLength=139 with Body length 0. 如果在代理到远程服务器之前删除api调用,请求可以通过并返回正确的响应 我的中间件如下所示: func AuthMiddleware(next http.Handler) http.Handler {

在将请求代理到远程服务器之前,我试图通过调用RESTAPI对用户进行身份验证。 但是,我发现如果我在代理到远程服务器之前调用api,请求将失败,并出现以下错误:

http: proxy error: http: ContentLength=139 with Body length 0.
如果在代理到远程服务器之前删除api调用,请求可以通过并返回正确的响应

我的中间件如下所示:

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                // the api call to external auth server
        user_id, err := authenticate(r.FormValue("username"), r.FormValue("password"))      
                if err != nil {
            http.Error(w, err.Error(), 401)
            return
        }
        next.ServeHTTP(w, r)
    })
}
func NewReverseProxy(target *url.URL) *httputil.ReverseProxy {
    director := func(req *http.Request) {
        req.URL.Scheme = target.Scheme
        req.URL.Host = target.Host
        req.URL.Path = target.Path
        targetQuery := target.RawQuery
        if targetQuery == "" || req.URL.RawQuery == "" {
            req.URL.RawQuery = targetQuery + req.URL.RawQuery
        } else {
            req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
        }
        if _, ok := req.Header["User-Agent"]; !ok {
            // explicitly disable User-Agent so it's not set to default value
            req.Header.Set("User-Agent", "")
        }
    }
    return &httputil.ReverseProxy{Director: director}
}
我的反向代理如下所示:

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                // the api call to external auth server
        user_id, err := authenticate(r.FormValue("username"), r.FormValue("password"))      
                if err != nil {
            http.Error(w, err.Error(), 401)
            return
        }
        next.ServeHTTP(w, r)
    })
}
func NewReverseProxy(target *url.URL) *httputil.ReverseProxy {
    director := func(req *http.Request) {
        req.URL.Scheme = target.Scheme
        req.URL.Host = target.Host
        req.URL.Path = target.Path
        targetQuery := target.RawQuery
        if targetQuery == "" || req.URL.RawQuery == "" {
            req.URL.RawQuery = targetQuery + req.URL.RawQuery
        } else {
            req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
        }
        if _, ok := req.Header["User-Agent"]; !ok {
            // explicitly disable User-Agent so it's not set to default value
            req.Header.Set("User-Agent", "")
        }
    }
    return &httputil.ReverseProxy{Director: director}
}
我使用Chi进行路由

r.Use(AuthMiddleware)
r.Post("/", NewReverseProxy(targets).ServeHTTP)

这个实现有什么问题

如果您不再关心正文,可以将请求的contentlength设置为0,以反映正文的当前状态:

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // the api call to external auth server
        user_id, err := authenticate(r.FormValue("username"), r.FormValue("password"))
        if err != nil {
            http.Error(w, err.Error(), 401)
            return
        }
        r.ContentLength = 0
        next.ServeHTTP(w, r)
    })
}

首先想到的是:你读过尸体并合上它吗?可能是@RickyA的复制品,谢谢。我认为
r.FormValue(“用户名”)
读取正文并关闭它。如果我真的需要得到这些值,你有什么建议?复制尸体?谢谢您除了发送凭据之外,您还使用正文吗?当使用
r.ContentLength=0
时,这意味着正文将通过代理而不进行任何修改?那么
r.ContentLength=-1
有什么区别呢?