Set map,struct to session in golang( gin gonic framework) - session

I am using gin gonic to build a web application. I use https://github.com/gin-gonic/contrib/tree/master/sessions to handle session. Forexample, i set a integer value to session:
function Test(c *gin.Context){
session:= sessions.Default(c)
session.Set("mysession",123)
session.Save()
}
And in another controllers, i can get this session by session.Get("mysession").
But if i set map or struct. I only can get the session in the same controller. something wrong here??

You probably forgot to register it, when your app starts you need to have something like:
package main
import (
"encoding/gob"
"path/to/yourpackage"
func init() {
gob.Register(&yourpackage.YourStruct{})
}
You can look here http://www.gorillatoolkit.org/pkg/sessions for more information (gin-gonic uses gorilla sessions under the hood)

Related

How do I find the request method from Go Gin context?

I want to use the same handler for multiple endpoints in a Go Gin app:
router.POST("/box/:boxID", controllers.AddUpdateBox)
router.PUT("/box/:boxID", controllers.AddUpdateBox)
router.PATCH("/box/:boxID", controllers.AddUpdateBox)
In the controller I want to find what is the request method (POST, PUT or PATCH).
func AddUpdateBox(c *gin.Context) {
}
How do I get the request method from the Gin context?
c.Request.Method
This member represents the method of the request
c.Request.Method
Struct http.Request on Package net/http has a property called Method that can be used to check the method on a currently running request.

how to use multiple negroni.Wrap()

I have an issue to implement middleware i want to use negroni.Wrap function for validate user location and one for calling handler below is my route:
r.Handle("/users/{userID}", negroni.New(
negroni.HandlerFunc(validateTokenMiddleware),
negroni.Wrap(&userLocation),
negroni.Wrap(&userDetailHandler),
)).Methods("GET")
and &userLocation is object of an struct which contain db information, here when i request for handler then that time both wrap execute together. But i want execute &userlocation first and if any errors occur so next wrap should not be execute , how to resolve this issue.
Thanks.
Use a middleware having ServeHttp Method which will be called using userDetailHandler as receiver inside middleware. And pass your db struct in middleware as an argument . You should use single wrap.
r.Handle("/users/{userID}", negroni.New(
negroni.HandlerFunc(validateTokenMiddleware),
negroni.Wrap(userDetailHandler.Middleware(&userLocation)),
)).Methods("GET")
func (userDetailHandler *UserDetailHandler)Middleware(res http.ResponseWriter, req *http.Request, userLocation *userLocation){
// use your serve Http inside this
userDetailHandler.ServeHttp(res, req)
}

Golang request middleware library?

I'm using gorrilla mux for my mux for my routing setup.
Is there any open source library that will provide some sort of request middleware?
router.HandleFunc("/products", GetProducts).Methods("GET")
So currently I have the GetProducts function that will return the products etc.
But this is a REST api that I am building, so I have to handle things like loading the user, verifying the 'api token' for the request etc.
I don't want to do this for each and every method so I was hoping I there was some request middleware when I can do this before/after execution, along with adding things like User, Permissions to the context in each middleware function.
You can use Go Gin HTTP web framework that supports middlewares as well as you want:
Using middleware:
func main() {
// Creates a router without any middleware by default
r := gin.New()
// Global middleware
// Logger middleware will write the logs to gin.DefaultWriter even you set with GIN_MODE=release.
// By default gin.DefaultWriter = os.Stdout
r.Use(gin.Logger())
// Recovery middleware recovers from any panics and writes a 500 if there was one.
r.Use(gin.Recovery())
// Per route middleware, you can add as many as you desire.
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
// Authorization group
// authorized := r.Group("/", AuthRequired())
// exactly the same as:
authorized := r.Group("/")
// per group middleware! in this case we use the custom created
// AuthRequired() middleware just in the "authorized" group.
authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
authorized.POST("/submit", submitEndpoint)
authorized.POST("/read", readEndpoint)
// nested group
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}

Revel Framework - Go Lang - Not able to find controller

I am using Revel framework for golang. I have a subdirectory in my controllers folder like below
controllers
new
app2.go
app1.go
Contents of app1.go
package controllers
import (
"github.com/revel/revel"
)
type APP1 struct {
*revel.Controller
}
func (c APP1) Show() revel.Result {
}
Contents of app2.go
import (
"github.com/revel/revel"
)
type APP2 struct {
*revel.Controller
}
func (c APP2) Show() revel.Result {
}
My routes file is like this
GET /v1/show APP1.show
GET /v2/show APP2.show
When I call /v2/show it gives me error failed to find controller APP2 while v1/show is working absolutely working fine. Can anybody tell me how to fix it.
Configure the route for APP2.show like this GET /new/v2/show
Add the below at the top of app2.go
package controllers
I tried the same using a similar example and it worked for me. I would suggest not to use full capitalized controller names; use App2 instead of APP2.
I was a little confused to find out that the methods referenced from the router need to be Pascal Cased to be recognized (e.g. like above func (c APP2) DescribeService() revel.Result). This might be obvious to seasoned Revel or Go developers but really wasn't obvious to me.

Testing handlers that use Gorilla/context

I'm using gorilla/context in a web app. The example in the docs looks like:
func MyHandler(w http.ResponseWriter, r *http.Request) {
//...
val := context.Get(r, foo.MyKey)
//...
}
How can I unit test a handler that works like this? The only way I've managed so far is to use the context package inside my tests. I'm thinking at the moment that I could inject a context parameter into the handler but then I'm not conforming to the HandlerFunc interface.
This is a classic cross-cutting concerns example.
You are using a 3rd party to magically handle input params for your unit under test. By that very definition, you are going to have to do some extra setup to prep the context for the state you want.
When it comes to Go http handlers (which the convention is to KISS it), you shouldn't need to "reach out of context" of your func to get extra data: keep all the data you need within your single func.
Personally, I try to avoid corrupting my handlers like this. I think I've only used gorilla's context once out of the dozens of big sites I've built. And that was basically to get around a cached response, just to keep the data refesh to the end user. Of which I simply ignored in my unit tests, as it was out-of-scrope of what I was testing.
Instead, I use middle-ware wrappers to setup the basics I want in my handles and modify the handler's signature accordingly.
caching
logging
authentication and authorization
json marshaling
context (e.g. expected User{} object loaded from DB)
...etc. I would create a middle-ware that wraps your handler when you register it with mux that uses gorilla/context to lookup your cookie or userid or something, hidrates that user object from cache, DB, redis, etc, and then calls your handler that would have a signature like:
func MyHandler(u User, p Page, w http.ResponseWriter, r *http.Request) {
// u is the User object loaded from middle-ware
// p is your global Page object... etc
}
That way, your unit tests inject only the items you need under test.
And you can integration test your middle-ware on a QA server with expected User and Page objects in a datastore.
The way my team does it is to add a name to the route handler and then in the tests we call that route by name.
This is how to add a route:
r.HandleFunc("/<route>", MyHandler).Methods("GET").Name("MyHandlerByName")
Then this is how to test it
r.Get("MyHandlerByName")
One way to test handles is modify the way in which they are created. for example, Creating a function that return a http.HandlerFunc, this function can have parameters. You can mock the values that you send to the function
Without parameters
func State() http.HandlerFunc {
return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request) {
// your code
})
}
With Parameters
func State(pParam1,pParam2,pParam3 ...) http.HandlerFunc {
return http.HandlerFunc(func(pResponse http.ResponseWriter, r *http.Request) {
// your code using pParam1,pParam2,pParam3
})
}
The mapping will be
http.HandleFunc("/State", State())
or
http.HandleFunc("/State", State(value1,value2,value3 ....))

Resources