graphql-go
graphql-go copied to clipboard
How to use viewer in context
I'm a little confused as to how I can implement the viewer methodology with this. I am looking to use this viewer method so that I will only use the queries that are in accordance to the relative user.
So you graphql schema might look like this
type Query {
viewer: Viewer
}
type Viewer {
id: ID!
name: String!
mail: String!
favourites: [Favourite]!
}
This would mean that viewer information will be relative to who is logged in, then you need to check for a token, cookie, or whatever method you got for it.
In my case i'm using json web tokens (jwt) so it might look like this
type viewerResolver struct {
user User
}
func (r *Resolver) Viewer(ctx context.Context) (*viewerResolver, error) {
var userID *string = nil
token := ctx.Value("jwt").(*jwt.Token)
if token != nil {
claims, _ := token.Claims.(jwt.MapClaims)
id := claims["sub"].(string)
userID = &id
}
user := getUser(userID)
return &viewerResolver{
user: user,
}, nil
}
I'm using this middleware function to get the token out of the http request header Authorization
and pass it down by context, which my viewer resolver above has access to it.
func auth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
token := r.Header.Get("Authorization")
jwt, err := checkToken(token)
if err != nil {
fmt.Println(err)
}
next.ServeHTTP(w, r.WithContext(context.WithValue(ctx, "jwt", jwt)))
})
}
And there is it, there you can get all the information relative to your user, if there is anything else you might need or have a question please let me know
@lpalmes Awesome! I will definitely try this out! I'll let you know if I have any more questions
@lpalmes What jwt library do you happen to be using?
Hey @saviodo5591, this one https://github.com/dgrijalva/jwt-go
I was running into a few issues with the claims option not showing up. Turns out I was using the standard "Context" library vs the "golang.org/x/net/context" package. The only other thing I'm a tad confused about is the getUser(userID) method, is this a resolver function or is it a database call? Additionally, the checkToken(token) seems to be throwing an unresolved reference. I'm probably missing that's really obvious but I can't seem to be getting it to work.
getUser and checkToken were private functions just to demonstrate the point. If you will I could make an example with everything in form of a repo or gist
That would actually be great! I tend to work better with actually seeing the code sometimes
Then I will create an example and let you know as soon as I’m able to. I’ll let you know in a couple of hours
Ok great thank you very much!
Hey @saviodo5591, here you go, a working example, everything is in the main.go file and the schema is on another file, it took longer than expected because i added users, login, and some extra stuff.
Don't mind the repo, is a graphql-go introduction i was writing but is on hold till the api comes along, again, hope it serves you well.
hi lpalmes , very beautiful example. thanx a lot. I was looking for some information on context.
@lpalmes Thanks for the example. First I did go get .
and I ran with go run main.go
. I got EOF as the output when I navigated to http://localhost:8080/graphql
Hey @smithaitufe, graphiql (the ui to graphql) is running at http://localhost:8080, and the route for sending the graphql queries is at /graphql
(Plain http post requests with the query) as seen in this line.
Glad you like it, and hope i'm begin useful, if you got any more questions just ask, drop an issue, anything and i do my best to help.
@lpalmes I checked again and it is working perfectly fine. The issue was my poor internet connection. Thanks so much. With time you must consider how to handle uploading of files, database access with the use of context etc. I can easily do that with Nodejs but I am considering porting my ecommerce backend to go
Hi, How can Resolvers pass Contexts to sub-Resolvers? I would like to set a value in my root queries available for sub-resolves, this would also be a crucial path towards batching request. Thanks, Dan.
Looks like the Tracer is for this purpose? Is there an example?
Maybe someone not so new to Go would have found this easier, but I ended up doing something like...
import trace "github.com/neelance/graphql-go/trace"
type ourTracer struct {
delegate trace.OpenTracingTracer
}
func (t ourTracer) TraceQuery(ctx context.Context, queryString string, operationName string, variables map[string]interface{}, varTypes map[string]*introspection.Type) (context.Context, trace.TraceQueryFinishFunc) {
//Stuff
return t.delegate.TraceQuery(ctx, queryString, operationName, variables, varTypes)
}
func (t ourTracer) TraceField(ctx context.Context, label, typeName, fieldName string, trivial bool, args map[string]interface{}) (context.Context, trace.TraceFieldFinishFunc) {
//Stuff
return t.delegate.TraceField(ctx, label, typeName, fieldName, trivial, args)
}