-
Notifications
You must be signed in to change notification settings - Fork 689
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filters to modify request? #71
Comments
You can used request attributes for this purpose. http://godoc.org/github.com/emicklei/go-restful#Request.SetAttribute Attributes values are of type interface{} so you should cast to *sql.Tx after accesing it. Let me know it this works for you. |
Thanks for the confirmation @emicklei - that looks quite clean! |
Wow, nice, I think we should document this better somehow.. I wanted to do this too, but ended up not finding a solution. I think I'll try to write an example for this. |
Here's some sample code from my app @stefreak: I happened to import //
// Extracts a TX from the request
//
func getRequestTx(r *restful.Request) *sql.Tx {
if rv := context.Get(r.Request, RequestTxKey); rv != nil {
return rv.(*sql.Tx)
}
return nil
}
//
// Used in testing to inject a TX which we can control
//
func InjectTx(tx *sql.Tx) restful.FilterFunction {
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
// Inject the open Tx into the request, and hope that things
// run smoothly.
context.Set(req.Request, RequestTxKey, tx)
// Launch the request up the stack
chain.ProcessFilter(req, resp)
}
}
//
// Used in the real world, to let the request drive the opening of a transaction
// for which we defer committing, or rolling back if things go wrong.
// This doesn't stop the handler committing, or rolling back the transaction,
// it it would, then the deferred callback will simply do nothing.
//
func InjectDeferredDbTx(db *sql.DB) restful.FilterFunction {
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
tx, err := db.Begin()
if err != nil {
panic(err)
}
fmt.Println("Handling Request, injecting a TX mofo")
// Refer something to run later, we try and
// catch any panics to stop the pq driver getting
// into a weird internal state, and issue a ROLLBACK
// if things went bad, otherwise commit the transaction
// and go on with our lives.
defer func(tx *sql.Tx) {
if r := recover(); r != nil {
tx.Rollback()
panic(r)
} else {
tx.Commit()
}
}(tx)
// Inject the open Tx into the request, and hope that things
// run smoothly.
context.Set(req.Request, RequestTxKey, tx)
// Launch the request up the stack
chain.ProcessFilter(req, resp)
}
} The usage in my handler is quite neat, too: func (sch sessionCreateHandler) ServeHTTP(req *restful.Request, res *restful.Response) {
tx := getRequestTx(req)
userStore := stores.NewDbUserStore(tx, sch.c)
sessionStore := stores.NewDbSessionStore(tx)
params := new(createSessionParams)
if err := req.ReadEntity(¶ms); err != nil {
res.WriteHeader(http.StatusBadRequest)
return
}
} |
Can this issue be closed? I will create an example from your snippet that uses request attributes when time permits. |
Yes, can absolutely be closed :-) perhaps if you have time (or if I do) we/you/I could contribute injecting something, and logging as examples. |
Please excuse me opening a GH issue for what I think is really just a question.
I have a use case where each request relies on having it's own
*sql.Tx
, and when the request does not err out, that should beCOMMIT
ted, when the request errs it should beROLLBACK
ed.I had hoped to use filters for this - (as well as authentication), in both cases, I'd need to be able to arbitrarily inject something into the request context.
I couldn't see it documented, if I wouldn't be experimenting with go-restfully, I'd probably use http://www.gorillatoolkit.org/pkg/context
Thanks for a really cool package.
The text was updated successfully, but these errors were encountered: