Gorilla Mux not handling my path - go

When I use the default router from http everything works, but if I use the router from gorilla/mux instead, I get a 404 page with the body 404 page not found. As shown in the samples below, everything else is exactly the same.
Why doesn't the gorilla/mux router work like this?
Working correctly, using http routing:
package main
import "net/http"
func simplestPossible(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("MWE says OK"))
}
func main() {
http.HandleFunc("/", simplestPossible)
http.ListenAndServe(":8000", nil)
}
Not working, using gorilla/mux routing:
package main
import "net/http"
import "github.com/gorilla/mux"
func simplestPossible(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("MWE says OK"))
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", simplestPossible)
http.ListenAndServe(":8000", nil)
}

You must pass your handler to http package (ListenAndServe):
http.ListenAndServe(":8000", r)

Related

how to create a reverse proxy in golang

I wants to make a reverse proxy in golang using net package from stl library. Used httputil for creating reverse proxy. But when I make request to the proxy server it return 404 error.
Here is the proxy server code
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
demoUrl , err := url.Parse("http://localhost:1000/run/")
if err!=nil{
log.Fatal(err)
return
}
proxy := httputil.NewSingleHostReverseProxy(demoUrl)
http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
proxy.ServeHTTP(rw, r)
})
http.ListenAndServe(":2000", nil)
}
Here is the origin server code :
package main
import (
"net/http"
)
func main(){
http.HandleFunc("/run", func(w http.ResponseWriter, r *http.Request){
w.Write([]byte("I am running"))
})
http.ListenAndServe(":1000", nil)
}
Please tell what I am missing here and how to fix the bug! Please
The router doesn't match.
this will be working as expected.
...
func main(){
http.HandleFunc("/run/", func(w http.ResponseWriter, r *http.Request){
w.Write([]byte("I am running"))
})
http.ListenAndServe(":1000", nil)
}
...

Serving favicon.ico with JulienSchmidt httprouter

I can get favicon.icon with the standard net/http package but am having trouble with julienschmidt/httprouter. This is what I'm trying and am receiving a 404 error for the favicon.ico file.
import (
"github.com/julienschmidt/httprouter"
"net/http"
"log"
)
func main(){
router := httprouter.New()
router.GET("/", index)
router.POST("/", login)
router.GET("/logout", logout)
router.GET("/favicon.ico", faviconHandler)
router.ServeFiles("/stuff/*filepath", http.Dir("stuff"))
log.Fatal(http.ListenAndServe(":8080", router))
}
func faviconHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
http.ServeFile(w, r, "/stuff/images/favicon.ico")
}
I was able to solve the problem by removing the leading slash from stuff/images/favicon.ico. Thanks #Peter.
import (
"github.com/julienschmidt/httprouter"
"net/http"
"log"
)
func main(){
router := httprouter.New()
router.GET("/", index)
router.POST("/", login)
router.GET("/logout", logout)
router.GET("/favicon.ico", faviconHandler)
router.ServeFiles("/stuff/*filepath", http.Dir("stuff"))
log.Fatal(http.ListenAndServe(":8080", router))
}
func faviconHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
http.ServeFile(w, r, "stuff/images/favicon.ico")
}

setup 404 NotFound handler on a gorilla mux router

Here is my code about a small demonstration webserver written with the Go language and the gorilla mux package :
package main
import (
"fmt"
"github.com/gorilla/mux"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
fmt.Fprintf(w, "Hi there, I love %s!", vars["username"])
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
errorHandler(w, r, http.StatusNotFound)
return
}
vars := mux.Vars(r)
fmt.Fprintf(w, "Hi there, I love %s!", vars["username"])
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/help/{username}/", handler)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}
But I don't find a way on how to implement a custom 404 page.
But I can't make a r.HandleFunc("/",...) but it will be too greedy.
The Router exports a NotFoundHandler field which you can set to your custom handler.
r := mux.NewRouter()
r.NotFoundHandler = MyCustom404Handler
Sometimes, you spend a lot of time building a stack of middleware that does many things like logging, sending metrics and so... And the default 404 handler just skips all the middlewares.
I was able to solve this issue by re-setting the default 404 handler like this:
router := mux.NewRouter()
router.Use(someMiddleware())
// Re-define the default NotFound handler
router.NotFoundHandler = router.NewRoute().HandlerFunc(http.NotFound).GetHandler()
Now, the 404 default handler is also going thru all the middlewares.
Set the NotFoundHandler to a handler method that returns your custom 404 page.
r := mux.NewRouter()
h := http.HandlerFunc(NotFound)
r.NotFoundHandler = h
func NotFound(w http.ResponseWriter, r *http.Request) {
}

Go simple API Gateway proxy

I've been searching all over the internet how to do this, but I haven't been able to find it. I'm trying to build a simple API gateway using Go and Martini for my system that has a few microservices with REST interfaces running. For example, I have my users service running on 192.168.2.8:8000, and I want to access it through /users
So my API gateway would look something like this:
package main
import (
"github.com/codegangsta/martini"
"net/http"
)
func main(){
app := martini.Classic()
app.Get("/users/:resource", func(req *http.Request, res http.ResponseWriter){
//proxy to http://192.168.2.8:8000/:resource
})
app.Run()
}
edit
I've got something working, but all i see is [vhost v2] release 2.2.5:
package main
import(
"net/url"
"net/http"
"net/http/httputil"
"github.com/codegangsta/martini"
"fmt"
)
func main() {
remote, err := url.Parse("http://127.0.0.1:3000")
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
app := martini.Classic()
app.Get("/users/**", handler(proxy))
app.RunOnAddr(":4000")
}
func handler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request, martini.Params) {
return func(w http.ResponseWriter, r *http.Request, params martini.Params) {
fmt.Println(params)
r.URL.Path = "/authorize"
p.ServeHTTP(w, r)
}
}
edit 2
This only seems to be a problem when using it directly through the browser, XMLHttpRequest works just fine
stdlib version
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
target, err := url.Parse("http://192.168.2.8:8000")
if err != nil {
log.Fatal(err)
}
http.Handle("/users/", http.StripPrefix("/users/", httputil.NewSingleHostReverseProxy(target)))
http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./Documents"))))
log.Fatal(http.ListenAndServe(":8080", nil))
}
Wrap http.StripPrefix with a function that logs before calling it if you need logging.

"Blank response" NotFoundHandler not working Gorilla

I am trying to debug 404-not-found by writing a custom not-found handler. Here is my code.
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/coopernurse/gorp"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
func main() {
// Create a MUX
r := mux.NewRouter()
http.Handle("/", r)
r.NotFoundHandler = http.HandlerFunc(NotFound)
// Static
r.PathPrefix("/app").HandlerFunc(uiAppHandler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}
func NotFound(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "custom 404")
}
func uiAppHandler(w http.ResponseWriter, r *http.Request) {
repoFrontend1 := "/UI/KD/WebContent"
http.StripPrefix("/app/", http.FileServer(http.Dir(repoFrontend1)))
}
I am getting a blank response for both existing and non-existing files. I guess NotFound is not getting triggered because of my "/" handler. Then how do I handle notFound for http.Dir?
Here is my directory structure
The response from uiAppHandler is blank because the function does not write to the response w. You should register the file server handler directly with the mux instead of trying to create a handler:
r.PathPrefix("/app").Handler(http.StripPrefix("/app/", http.FileServer(http.Dir(repoFrontend1))))
The mux passes all requests with the prefix "/app" to the handler registered for that prefix. All requests with that prefix are found as far as the mux is concerned. The http.FileServer or whatever you register for that prefix is responsible for generating the 404 response.

Resources