Request Context

HTTP Scaffolding

Request Context

🙋 Need help? Ask an expert now!

Per-request Data

Frequently, we need to access data like the requesting user or client multiple times throughout the lifecycle of an HTTP request. For this reason, we utilize the Go context API and some primitive wrapper funcs.

Reqctx

In our reqctx/reqctx.go (pronounced "Request Context") file, we create some boilerplate functions for handling the notion of a requesting user:

package reqctx
            
            import (
                "context"
                "errors"
                "github.com/exlinc/golang-utils/htmlhttp"
                "github.com/exlinc/golang-utils/jsonhttp"
                "github.com/exlskills/demo-go-webservice/models"
                "net/http"
            )
            
            const currentUserContextKey = "req_usr"
            
            var unauthorizedError = jsonhttp.APIResponse{Message: "Unauthorized", Success: false, Debug: "Token/account error"}
            
            func AddCurrentUserToContext(r *http.Request, user models.User) context.Context {
                return context.WithValue(r.Context(), currentUserContextKey, user)
            }
            
            func GetCurrentUser(r *http.Request) (models.User, error) {
                user := r.Context().Value(currentUserContextKey)
                switch user.(type) {
                case nil:
                    return models.User{}, errors.New("current user not found")
                default:
                    return user.(models.User), nil
                }
            }
            
            func GetCurrentUserAndCatchForAPI(w http.ResponseWriter, r *http.Request) (models.User, error) {
                var user models.User
                user, err := GetCurrentUser(r)
                if err != nil || user.ID == 0 {
                    jsonhttp.JSONWriter(w, unauthorizedError, http.StatusUnauthorized)
                    return user, err
                }
                return user, nil
            }
            
            func GetCurrentUserAndCatchForView(w http.ResponseWriter, r *http.Request) (models.User, error) {
                var user models.User
                user, err := GetCurrentUser(r)
                if err != nil || user.ID == 0 {
                    htmlhttp.UnauthorizedErrorView(w, r)
                    return user, err
                }
                return user, nil
            }
Edit Me on GitHub!