I am trying to authenticate a user by calling a REST api, before I proxy the request to a remote server. However, I find that if I make the api call before proxy to remote server, the request will fail with the following error:
http: proxy error: http: ContentLength=139 with Body length 0.
If I remove the api call before proxy to remote server, the request can get through and return correct response.
My middleware is as following:
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)
})
}
My reverse proxy is as following:
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}
}
And I am using Chi for routing
r.Use(AuthMiddleware)
r.Post("/", NewReverseProxy(targets).ServeHTTP)
What is the issue with this implementation?
If you do not care for the body anymore you can set the contentlength of the request to 0, reflecting the current state of the body:
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)
})
}