Negroni and Gorilla Context ClearHandler - go

Is is possible to use Gorilla's context.ClearHandler() as middleware for Negroni like I've seen it used as middleware for Alice? Something like:
n.Use(context.ClearHandler())
At the moment I'm calling context.Clear(r) after every response but I would prefer the tidying up to be taken care of automatically. I'm currently getting the following error:
cannot use context.ClearHandler() (type http.Handler) as type negroni.Handler in argument to n.Use:
http.Handler does not implement negroni.Handler (wrong type for ServeHTTP method)
have ServeHTTP(http.ResponseWriter, *http.Request)
want ServeHTTP(http.ResponseWriter, *http.Request, http.HandlerFunc)
But I'm not sure what the error message is telling me.

Negroni.Use() expects a parameter of type negroni.Handler but Gorilla's context.ClearHandler() returns a value of type http.Handler.
Good thing is that there is an alternative Negroni.UseHandler() method which expects an http.Handler so just use that. Note that context.ClearHandler() also expects another http.Handler:
otherHandler := ... // Other handler you want to clear
n.UseHandler(context.ClearHandler(otherHandler))
Notes:
The Router from the gorilla/mux package automatically calls context.Clear() at the end of a request lifetime, so if you are using it you don't need to clear the context using context.ClearHandler(). You only need to use it for other / custom handlers (unless you want to call context.Clear() manually).

Related

In Go gin framework , how to get all url that I have registered in the router

I’m programming the role based access control with casbin. However ,the police need me to provide urls that the role has. The “v1” column in the table, see the picture.
I wondered can I get all urls that I registered in router. So that I don’t need to add by my hand.
You can use Routes which would return slice of RoutesInfo through which you can get all the register route path plus additional informaiton.
RoutesInfo will contain below struct from which required information can be retrieved.
type RouteInfo struct {
Method string
Path string
Handler string
HandlerFunc HandlerFunc
}
r := gin.Default()
r.Routes()

Is there a way to pass in headers through Http.Handle or Http.FileServer?

I have a very basic server set up in Go
fs := http.FileServer(http.Dir("./public"))
http.Handle("/",fs)
Here's the problem though: I want people to access my URL's with fetch(). This isn't possible, however due to CORS being set.
Access to fetch 'xxxxx' from origin 'null' has
been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch
the resource with CORS disabled.
I need to find a way to pass in the header Access-Control-Allow-Origin:*, but I don't know how to with http.Handle or http.FileServer, only http.HandleFunc.
I can't use http.HandleFunc because as far as I know it doesn't allow me to serve files, and I'd rather not get files myself using a file handling system (I may have to do this as a last resort unless there is another way). Plus, it's inefficient. Why reinvent the wheel, especially when that wheel is way better than what I could come up with?
Is there any way whatsoever to send headers with http.Handle()?
I am fairly new to Go, and I haven't done statically typed languages in a while, nor have I done languages that handle incoming URL's (I mainly used PHP, so...), so I may or may not have a good grasp on the concept.
You can wrap a http.FileServer in a http.HandleFunc:
func cors(fs http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// do your cors stuff
// return if you do not want the FileServer handle a specific request
fs.ServeHTTP(w, r)
}
}
Then use it with:
fs := http.FileServer(http.Dir("./public"))
http.Handle("/", cors(fs))
The underlying mechanism is that http.HandlerFunc implements the http.Handler interface.

Variables for goroutines

Im currently making a web app using Go. I want to know on my templates when the user is logged in or not and I am currently making it using this approach
response := &viewCharacter{true}
template.Renderer.ExecuteTemplate(w, "character_search.html", response)
As you see I am passing a viewCharacter struct that only contains a bool Logged then on a template I can do the following
{{ if .Logged }}
Is there any other approach to do this? instead of passing on each template a logged bool?
Maybe setting a variable for each goroutine of the http handler that saves if the user is logged or not?
There are only two ways that I know to communicate between the go code and the template.
The first one is the one you use. By passing a struct to the ExecuteTemplate function you can access all its field in the template.
The second one is to register other functions using:
func (t *Template) Funcs(funcMap FuncMap) *Template
See documentation for more information. The funcMap is a simple map[string]interface{}, you can register any function and call it in the template by using its name (the key of the map).

How to get OR pattern in Gorilla mux routing

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",

GoLang Gin Framework Status Code Without Message Body

I'm using GoLang and Gin Framework.
I need to respond for REST API call with 204 response code without message body.
How it is to do properly?
What I could find by digging the source code
c.JSON(204, "")
But server throws error at such case:
Error #01: http: request method or response status code does not allow body
Meta: []
Any ideas?
You could use c.AbortWithStatus(204), with the one caveat that when you use abort, the rest of pending handlers will never be called for that request.
Or, you could do:
c.Writer.WriteHeader(204)
and let your program continue normally (but making sure not to write out anything else)
adding on #depado comments,
c.Status(http.StatusNoContent) is the simplest way to achieve this.
Works with gin v1.6.3
up to now, the function Abort's prototype is
func (c *Context) Abort()
you can use AbortWithStatus instead c.AbortWithStatus(204), whose prototype is
func (c *Context) AbortWithStatus(code int)

Resources