package response import ( "context" "net/http" "net/url" "strconv" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) type ctxKey string const ( CtxUserId ctxKey = "X-User-Id" CtxUserName ctxKey = "X-User-Name" CtxRefresh ctxKey = "X-Refresh" CtxServiceCode ctxKey = "X-Service-Code" ) type UserInfo struct { ID int64 Name string RawUID string Refresh string Valid bool } func GetUserInfo(ctx context.Context) UserInfo { rawUID, _ := ctx.Value(CtxUserId).(string) name, _ := ctx.Value(CtxUserName).(string) refresh, _ := ctx.Value(CtxRefresh).(string) info := UserInfo{ RawUID: rawUID, Name: name, Refresh: refresh, } if rawUID == "" { return info } uid, err := strconv.ParseInt(rawUID, 10, 64) if err != nil { info.Valid = false return info } info.ID = uid info.Valid = true return info } func UserReadMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { newCtx := r.Context() newCtx = context.WithValue(newCtx, CtxUserId, r.Header.Get("X-User-Id")) newCtx = context.WithValue(newCtx, CtxUserName, r.Header.Get("X-User-Name")) newCtx = context.WithValue(newCtx, CtxRefresh, r.Header.Get("X-Refresh")) next(w, r.WithContext(newCtx)) } } func UserClientInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { user := GetUserInfo(ctx) md := metadata.New(map[string]string{}) if user.Valid { md.Set("x-user-id", user.RawUID) md.Set("x-user-name", url.QueryEscape(user.Name)) } if user.Refresh != "" { md.Set("x-refresh", user.Refresh) } ctx = metadata.NewOutgoingContext(ctx, md) return invoker(ctx, method, req, reply, cc, opts...) }