Open jaytxrx opened 2 years ago
at a quick glance, this looks good. maybe the wildcard check doesn't work? try to change "*.example.com"
with "sub.example.com"
and see if that solves it?
I tried with sub.example.com. But still have the issue.
While debugging the code (route_headers.go), I found that the header information is not available in r.Header.Get(header)
Below fix (line 91) helped me to get the header details.
headerValue := r.Host //r.Header.Get(header)
Also I noticed that my browser is not sending the header details. I had to use curl to send header info.
After this the subdomain part works. But when accessing the main domain, the app crashes. I think still there are issues (maybe with the pattern functions). It would be a great help if someone can test the subdomain route header example and fix the issue.
please paste sample / minimal main.go program with the issue (with the crash)
I have pasted below the code. Note that the behavior from CURL and browser are different. Crash report from the app when using CURL is shown at the end.
1) Fix done in route_headers.go line 91 is shown below
headerValue := r.Host //r.Header.Get(header)
2) My subdomain code is shown below
package main
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
rSubdomain := chi.NewRouter()
r.Use(middleware.RouteHeaders().
Route("Host", "example.com", middleware.New(r)).
Route("Host", "sub.example.com", middleware.New(rSubdomain)).
Handler)
r.Get("/", h)
rSubdomain.Get("/", h2)
http.ListenAndServe(":8080", r)
}
func h(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Main domain")
}
func h2(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Sub domiain")
}
3) First I will start with the browser responses. Irrespective of sub.example.com or example.com, the response is always "Main domain". Even though the browser is sending the Host (see the attached images) it seems that the go application is not getting the Host details and hence always providing the same response. sub.example.com example.com
4) CURL responses
$ curl --header 'Host: sub.example.com' 'sub.example.com:8080'
Sub domiain
curl --header 'Host: .example.com' 'example.com:8080'
Main domain
curl --header 'Host: example.com' 'example.com:8080'
curl: (52) Empty reply from server
While sending 'Host: example.com', the app crashed. Crash report is here
The RouteHeaders
middleware can't be used to for Host matching. The example in route_headers.go
should be updated to reflect this or exclude the example entirely.
From https://pkg.go.dev/net/http
For incoming requests, the Host header is promoted to the Request.Host field and removed from the Header map.
In the meantime you can try https://github.com/go-chi/hostrouter
Also in the example the router (r
) seems to be mounted onto itself which is what's causing the stack overflow.
Just wanted to add my two cents here. I followed the example as well and also couldn't get it to work. As js-everts
mentioned, I don't believe it will work based on the code it's using.
I also tried using hostrouter
and couldn't get that to work either. I was about to give up until I realized that:
@felicianotech can you please paste the working code here ?
@felicianotech can you please paste the working code here ?
Sure
So what I've attempted to do is taking my actual, working code for my private project, and simplified it to what should be needed for this example. I hope it helps.
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/hostrouter"
log "github.com/sirupsen/logrus"
)
func main() {
// create routers
// coreRouter will be the top-level router that the hostrouter will be
// mounted to.
coreRouter = chi.NewRouter()
// webappRouter is the main router for my app. The entire
// webapp/backend system is powered using this router/these routes.
webappRouter = chi.NewRouter()
// publicRouter is used only for the wildcard subdomains to serve very
// basic and simple pages.
publicRouter = chi.NewRouter()
webappRouter.Use(loggingMiddleware)
webappRouter.Use(authMiddleware)
// manages static files for the main webapp
webappRouter.Get("/assets/*", func(w http.ResponseWriter, r *http.Request) {
http.StripPrefix("/assets/", http.FileServer(http.Dir(a.ThemeRoot+"static"))).ServeHTTP(w, r)
})
// manages static files for the simply website on subdomains (uses different assets)
publicRouter.Get("/assets/*", func(w http.ResponseWriter, r *http.Request) {
http.StripPrefix("/assets/", http.FileServer(http.Dir(a.ThemeRoot+"public-static"))).ServeHTTP(w, r)
})
// here is where the host mapping to sub-routers take place
// if you're using non-standard ports for http or https, the port
// number needs to show up here
hr := hostrouter.New()
hr.Map("*.myapp.com:9000", publicRouter)
// this matches anything not matched above
hr.Map("*", webappRouter)
// these are functions I have, in a different file, where I add the
// routers that belong to each router/webapp
addWebappRoutes()
addPublicRoutes()
// the hostrouter gets mounted to the core router here, completing the setup
coreRouter.Mount("/", hr)
// an HTTP server is run with the core router
log.Fatal(http.ListenAndServe(":9000", coreRouter))
}
A little update I learned from my previous post. The port numbers are needed when you are using them directly in the browser/curl. This applies to a dev environment for example. When I got my app in production, since it was behind a proxy, I actually had to not use the port numbers for the prod environment in order to get it to work.
Hi, can someone please provide a PR with a fix to the example code, if this is still a valid issue?
I implemented the subdomain example provided in the route_headers.go file. Unfortunately the example provided is not working. The issue is that sub.example.com goes to the main domain page instead of sub domain page. Can anyone please let me know how to fix the issue ? Or if the below code is working for them ?
I was testing on my local Ubuntu PC and following are the contents of /etc/hosts $ cat /etc/hosts 127.0.0.1 localhost 127.0.0.1 example.com 127.0.0.1 sub.example.com