Controlling gRPC JSON gateway cookies

Derek Young
Nov 6, 2018 · 5 min read

Controlling the response with gRPC metadata

SignIn — Session creation

func SetUserIDInContext(ctx context.Context, userID int) {  // create a header that the gateway will watch for  header := metadata.Pairs("gateway-session-userId", strconv.Itoa(userID))  // send the header back to the gateway  grpc.SendHeader(ctx, header)}
md, ok := runtime.ServerMetadataFromContext(ctx)if !ok {  return fmt.Errorf("Failed to extract ServerMetadata from context")}// did the gRPC method set a user ID in the metadata?userID, err := getUserIDFromServerMetadata(md)if err != nil {  return err}if userID != 0 {  rlog.Debugf("gRPC call set userId to %d", userID)  // pull the request from context (set in middleware above)  request := getRequestFromContext(ctx)  // create or get the session  session, err := sessionStore.New(request, defaultSessionID)  if err != nil {    rlog.Error(err, "couldn't create a session")    return err  }  session.Options.MaxAge = sessionLength  session.Options.Path = "/"
// create a session for the user. This session is converted by gorilla // into a session cookie userIDSession := &Session{ UserID: userID, } // put the userId into session session.Values["userId"] = userIDSession // save the session, creating a cookie from it if err := sessionStore.Save(request, response, session); err != nil { rlog.Error(err, "couldn't save the session as a cookie") return err }}
func (middleware *gatewayMiddleware) Middleware(next http.Handler) http.Handler {  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {    ctx := r.Context()    if ctx == nil {      ctx = context.Background()    }    ctx = context.WithValue(ctx, requestContextKey, r)    next.ServeHTTP(w, r.WithContext(ctx))  })}

SignOut — Session removal

Passing the user ID to gRPC calls

// look up session and pass userId in to context if it existsfunc gatewayMetadataAnnotator(_ context.Context, r *http.Request) metadata.MD {  session, err := sessionStore.Get(r, defaultSessionID)  if err != nil {    // no session, or invalid session, so pass along no extra metadata    return metadata.Pairs()  }  if userIDSessionValue, ok := session.Values["userId"]; ok {    // convert back to a Session    userIDSession := userIDSessionValue.(*Session)    userID := userIDSession.UserID    // set user ID from session in the gRPC metadata    return metadata.Pairs("userId", strconv.Itoa(userID))  }  // otherwise pass no extra metadata along  return metadata.Pairs()}

Demo source code

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade