forward to localhost returns 404
Do you know why my localhost is returning 404?
Here's the code:
// broken.go
package main
import (
"fmt"
"html"
"net/http"
"github.com/vulcand/oxy/forward"
"github.com/vulcand/oxy/testutils"
"github.com/urfave/negroni"
)
func main() {
// Forwards incoming requests to whatever location URL points to,
// adds proper forwarding headers
fwd, _ := forward.New()
redirect := func(w http.ResponseWriter, r *http.Request) {
url := testutils.ParseURI("http://localhost:3838/sample-apps/hello")
r.URL = url
r.Host = url.Host
fwd.ServeHTTP(w, r)
}
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
mux.HandleFunc("/myapp", redirect)
n := negroni.Classic() // Includes some default middlewares
n.UseHandler(mux)
http.ListenAndServe(":8011", n)
}
go run broken.go
[negroni] 2018-01-31T01:52:23Z | 200 | 97.89µs | localhost:8011 | GET /shiny
INFO[0006] vulcand/oxy/forward/http: Round trip: http://localhost:3838/sample-apps/hello, code: 404, Length: 849, duration: 6.862264ms
[negroni] 2018-01-31T01:52:27Z | 404 | 6.946216ms | localhost:3838 | GET /sample-apps/hello
^Csignal: interrupt
In contrast, this works perfectly well and the localhost app loads as it is supposed to:
// works.go
package main
import (
"net/http"
"github.com/vulcand/oxy/forward"
"github.com/vulcand/oxy/testutils"
)
func main() {
fwd, _ := forward.New()
redirect := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
req.URL = testutils.ParseURI("http://localhost:3838/sample-apps/hello")
fwd.ServeHTTP(w, req)
})
s := &http.Server{
Addr: ":8011",
Handler: redirect,
}
s.ListenAndServe()
}
I don't know how to inspect the HTTP headers, but I think that may be one way to solve this problem.
I guess that the Forwarded header is not set correctly, or perhaps some other header needs to be changed.
If I understand HTTP correctly, then there are 4 HTTP headers to inspect:
-
User request to Proxy server
-
Proxy server request to Backend application
-
Backend application response to Proxy server
-
Proxy server response to User
It might be useful to directly compare the set of 4 headers in two scenarios:
-
The golang proxy (as shown above), where behavior is not correct. So, the headers are probably not correct.
-
A similar Apache or nginx proxy, where behavior is correct. These headers should be correct, and could provide a hint about what to change in the golang proxy.
A correct Apache proxy setup looks like this:
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
Redirect /app /app/
ProxyPass /app/ http://localhost:3838/
ProxyPassReverse /app/ http://localhost:3838/
ProxyPreserveHost On
</VirtualHost>
If you'd like to share any ideas or tips, I'd greatly appreciate it!