Skip to content
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

How to access access API struct inside operator handler #661

Closed
menta2k opened this issue Sep 10, 2016 · 9 comments · Fixed by #1342
Closed

How to access access API struct inside operator handler #661

menta2k opened this issue Sep 10, 2016 · 9 comments · Fixed by #1342
Labels

Comments

@menta2k
Copy link

menta2k commented Sep 10, 2016

My question is how i can access the generated API interface from operator handler function ?
Can i pass it somehow via context or any other way to do that ?

@casualjim
Copy link
Member

it's not reachable from within the handler anywhere atm. I'm curious about what use case this would enable?

@menta2k
Copy link
Author

menta2k commented Sep 10, 2016

Thanks for the answer will try to find another workaround.
And about the use case its probably not relevant and its really custom.

I created an module like apache access module ACL based on IP address for different url. Instand of URL for lookup key i was decided to use Operation.ID. (lookup will be faster in that way because each operation have unique id according to swagged specification )

The problem comes when i wont to check against that ACL
There is 2 options to place a "hook" in golbalMiddleware or in each Operation Handler.
If i go for an golbalMiddleware a need to get an middleware.MatchedRoute.
Because i did not found a way to do that I add my ACL struct to the API struct and was thinking that i can access ACL property somehow from the context but did not found a way to do that.

@casualjim
Copy link
Member

ah ok this is possible in 2 ways.

The first way is by using an authenticator, the second way is making a middleware (not global)

Authenticator

// Authenticator represents an authentication strategy
// implementations of Authenticator know how to authenticate the
// request data and translate that into a valid principal object or an error
type Authenticator interface {
    Authenticate(interface{}) (bool, interface{}, error)
}

The schemes currently supported you can see here: https://github.com/go-openapi/runtime/tree/master/security

Middleware

// The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
// The middleware executes after routing but before authentication, binding and validation
func setupMiddlewares(handler http.Handler) http.Handler {
    return handler
}

to get to the matched route in one of those you can

import "github.com/gorilla/context"
context.Get(3, request)

That gets you a matched route.

Also it might be worth it to expose Context as an exported method on the api builder, that would be a simple PR to add the following code to go-swagger

func (o *LifecycleManagerAPI) Context() *middleware.Context {
    if o.context == nil {
        o.context = middleware.NewRoutableContext(o.spec, o, nil)
    }
    return o.context
}

then your middlware could take a context in and use RouteInfo(request) like this one: https://github.com/go-openapi/runtime/blob/master/middleware/security.go

@SandyWalsh
Copy link

Perhaps related to this ... I have some domain objects I need access to in the handlers (db connection, telemetry client, etc). What's the recommended way/place to define these and access them in the handlers? Would I define them in configure_xxx() and make wrapper functions for the handlers to make them accessible? Or is there a nice way to add them to the context? Perhaps some middleware to stuff it in?

I was looking for some examples of this but couldn't find anything.

@casualjim
Copy link
Member

Look at this one: https://github.com/go-openapi/kvstore

@SandyWalsh
Copy link

Thanks again @casualjim

I guess the important takeaway is that main and the handlers have to be pulled outside of the generated code since only configure_xxx() is protected. And main() doesn't call configureAPI() ... that was a little confusing looking through the other examples and not seeing any changes to the vanilla config code.

"It has to be there somewhere ..."

@SandyWalsh
Copy link

Hey @casualjim ... related to above discussion, wouldn't it be better to have all the handlers automatically be part of a default struct that simply has a Context member variable or empty interface? That would save everyone a lot of copy/pasta when we need to inject some info.

@casualjim
Copy link
Member

You mean a different context than the one available on params.HTTPRequest.Context() ?
More like an application level context?

@SandyWalsh
Copy link

yes, exactly. Something I can stuff a database reference or other business state into.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants