vulcand / oxy

Go middlewares for HTTP servers & proxies
Apache License 2.0
2.04k stars 323 forks source link

forward to localhost returns 404 #115

Open slowkow opened 6 years ago

slowkow commented 6 years ago

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()
}
slowkow commented 6 years ago

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:

  1. User request to Proxy server

  2. Proxy server request to Backend application

  3. Backend application response to Proxy server

  4. Proxy server response to User

It might be useful to directly compare the set of 4 headers in two scenarios:

  1. The golang proxy (as shown above), where behavior is not correct. So, the headers are probably not correct.

  2. 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!