I want to serve the swagger-ui using gorilla/mux and http.FileServer.
This is the routing that works so far:
router := mux.NewRouter()
router.PathPrefix("/swagger-ui/").Handler(http.StripPrefix("/swagger-ui/",
http.FileServer(http.Dir("swagger-ui/"))))
http.ListenAndServe(":8080", router)
The problem is: only a GET /swagger-ui/ returns the swagger page.
When I do (what most users also expect) a GET /swagger-ui without trailing slash I get a 404.
How can this be solved?
You have probably found the answer as the question is nearly two years old, but I will write the answer here so that anybody who comes across this question can see it.
You just need to define your gorilla router as:
router := mux.NewRouter().StrictSlash(true)
StrictSlash func(value bool) *Router StrictSlash defines the trailing
slash behavior for new routes. The initial value is false.
When true, if the route path is "/path/", accessing "/path" will
perform a redirect to the former and vice versa. In other words, your
application will always see the path as specified in the route.
When false, if the route path is "/path", accessing "/path/" will not
match this route and vice versa.
The re-direct is a HTTP 301 (Moved Permanently). Note that when this
is set for routes with a non-idempotent method (e.g. POST, PUT), the
subsequent re-directed request will be made as a GET by most clients.
Use middleware or client settings to modify this behaviour as needed.
Special case: when a route sets a path prefix using the PathPrefix()
method, strict slash is ignored for that route because the redirect
behavior can't be determined from a prefix alone. However, any
subrouters created from that route inherit the original StrictSlash
setting.
Related
Below is a snapshot of a HTTP Get Call while using Gorilla Mux Router:
usersAPIs.HandleFunc("/users",
middleware.WrapperHandler(th.List)).
Queries("email", "{email}").
Queries("order_by", "{order_by}").
Queries("order_type", "{order_type}").
Queries("page", "{page}").
Queries("limit", "{limit}").
Methods("GET")
Now when GET call happens with all query params e.g.
http://localhost:xxxx/accounts/users?email=a&page=1&limit=4&order_by=a&order_type=b
then the gorilla mux router matches the pattern and takes it to the handler.
But when called like with fewer parameters e.g.
http://localhost:xxxx/accounts/users?email=a&page=1
then it says e.g. 404 not found means Resource path not mapped.
Questions :
#1. What has been missed here, is Go Gorilla Mux Router need all query params?
#2. What to be done If the GET query can come with zero or more parameters? e.g.
http://localhost:xxxx/accounts/users?email=a&page=1
or
http://localhost:xxxx/accounts/users?page=1
Queries(key, value) acts as a path matcher when passed to the route. Since 5 path params are expected, the route would match only if all 5 of them are present.
Though it's a little late to answer this question, but for anyone who stubles upon it later.
I was creating restful API with Golang and I put the delete router after the getOne router by index, and the delete router never got triggered? I don't know why? When I reverse them, it works!
Can someone know the reason??
This is for Building Restful API with Golang.
Not works:
myRouter.HandleFunc("/article", createNewArticle).Methods("POST")
myRouter.HandleFunc("/article/{id}", getOneArticle)
myRouter.HandleFunc("/article/{id}", deleteArticle).Methods("DELETE")
Works!
myRouter.HandleFunc("/article", createNewArticle).Methods("POST")
myRouter.HandleFunc("/article/{id}", deleteArticle).Methods("DELETE")
myRouter.HandleFunc("/article/{id}", getOneArticle)
When I test the api using postman with DELETE methods, it always trigger the getOneArticle and respond with the delete item, but did not actually delete in the database!
You're using gorilla/mux. When an HTTP request comes in, this router tries to match routes in the order in which you add them.
When you add the route without specifying an HTTP method, it applies to all HTTP methods.
So, if your more specific route matching the DELETE method comes first, then it will match DELETE method calls, and the next route will match all methods. While it would match DELETE also, an actual DELETE call would never reach it because of the route preceding it.
But if you reverse them, the route which doesn't specify an HTTP method will match all methods, including DELETE.
Gorilla/mux matches the routes in an order in which you have defined them. Without specifying the Http Method it will match it no matter what you have selected from the postman i.e. GET, DELETE
for instance, you have a route /todo/1 and the method is not specified, It will run in case of GET, DELETE, POST and PUT.
Note
Same route with method DELETE defined under the first one will never get triggered.
I want to have a parameter with slashes in the router in gin.
From what I gathered I can do this by adding a wildcard to the URL. For example: /api/v0/files/*addr
But this approach doesn't work if I want to have the addr in the middle of the URL like /api/v0/*addr/files, and it returns this error:
catch-all routes are only allowed at the end of the path.
I was wondering whether there is another way of having it?
Seems that is a limitation of the Gin framework, as seen # https://github.com/gin-gonic/gin/blob/master/tree.go#L322
You could always invert the order and do a rewrite using a proxy and a regexp (i.e. /api/v0/*addr/files to /api/v0/files/*addr) or only accept methods ending with /files inside your handling function, but I'm afraid that is a hardcoded limitation of the Gin framework.
While developing a REST api in Go, how can we use path params? meaning to say what will be the format of the URI?
http://localhost:8765/myapp/{param1}/entries/{param2}
I tried using something like this to create the route but the handler function is not getting invoked.
Please note that, i intent to use only the net/http package , not any other web framework like gorilla mux.
What I tend to do is nested handlers. "/" is handled by the root handler. It pops the first part of the path, assigns the rest back to req.URL.Path (effectively acting like StripPrefix), determines which handler handles routes by that prefix (if any), then chains the appropriate handler. If that handler needs to parse an ID out of the path, it can, by the same mechansim - pop the first part of the path, parse it as necessary, then act.
This not only has no external dependencies, but it is faster than any router could ever be, because the routing is hard-coded rather than dynamic. Unless routing changes at runtime (which would be pretty unusual), there is no need for routing to be handled dynamically.
Well this is why people use frameworks like gin-gonic because this is not easy to do this in the net/http package IIUC.
Otherwise, you would need to strings.Split(r.URL.Path, "/") and work from those elements.
With net/http the following would trigger when calling localhost:8080/myapp/foo/entries/bar
http.HandleFunc("/myapp/", yourHandlerFunction)
Then inside yourHandlerFunction, manually parse r.URL.Path to find foo and bar.
Note that if you don't add a trailing / it won't work. The following would only trigger when calling localhost:8080/myapp:
http.HandleFunc("/myapp", yourHandlerFunction)
I'm trying to use Gorilla mux router to handle paths that respond to a limited list of strings in the URL. The service I am developing will take files from the caller and pass them through an "adapter" that send them to S3 or OneDrive, depending on the "adapter" specified in the URL. I also require a variable named "schema", which I only mention now because of the weirdness that follows. My test is as follows ({schema} will be set to "test"):
router.HandleFunc("/{adapter:(s3|onedrive)}/{schema:[a-z]+}/check",
func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf(`{"a":"%s","s":"%s"}`,
mux.Vars(r)["adapter"], mux.Vars(r)["schema"])))
}).Methods("GET")
I would expect that going to /s3/test/check would yield {"a":"s3","s":"test"} just as going to /onedrive/test/check should yield {"a":"onedrive","s":"test"} ... however in these cases I am getting {"a":"s3","s":"s3"} and {"a":"onedrive","s":"onedrive"} respectively.
The (s3|onedrive) check seems to be enforced because, for example, trying to go to /dropbox/test/check correctly yields a 404.
Why is the {schema} variable getting the value of the {adapter} variable and how can I fix this?
I think it's because of parenthesis which denote capturing group and yield submatch. It can interfere with gorilla matcher. Just try without parenthesis.
router.HandleFunc("/{adapter:s3|onedrive}/{schema:[a-z]+}/check",