go - 传入请求:带有自定义类型字段的上下文
问题描述
我正在使用 go 编写一个或多或少简单的 Web 应用程序,它提供了一个 rest api。当请求进来时,我想将用户的 id 临时存储在请求上下文中,它是 api 令牌的一部分。在阅读 了一些 文章和文档之后,我仍然很困惑如何确保使用 附加到上下文的值context.WithValue()
可以在没有类型断言的情况下使用,而是使用某种结构。
到目前为止,这是我想出的:
// RequestContext contains the application-specific information that are carried around in a request.
type RequestContext interface {
context.Context
// UserID returns the ID of the user for the current request
UserID() uuid.UUID
// SetUserID sets the ID of the currently authenticated user
SetUserID(id uuid.UUID)
}
type requestContext struct {
context.Context // the golang context
now time.Time // the time when the request is being processed
userID uuid.UUID // an ID identifying the current user
}
func (ctx *requestContext) UserID() uuid.UUID {
return ctx.userID
}
func (ctx *requestContext) SetUserID(id uuid.UUID) {
ctx.userID = id
}
func (ctx *requestContext) Now() time.Time {
return ctx.now
}
// NewRequestContext creates a new RequestContext with the current request information.
func NewRequestContext(now time.Time, r *http.Request) RequestContext {
return &requestContext{
Context: r.Context(),
now: now,
}
}
// RequestContextHandler is a middleware that sets up a new RequestContext and attaches it to the current request.
func RequestContextHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
next.ServeHTTP(w, r.WithContext(NewRequestContext(now, r)))
})
}
我想知道如何在处理程序中访问请求上下文的SetUserID()
和UserID()
函数,或者是否有替代的类似方法。
解决方案
要使用您构建的内容,您必须使用类型断言:
rctx:=request.Context().(RequestContext)
如果您有一个以与您相同的方式包装上下文的中间件,这将中断。
另一种方法是使用基本上下文,并添加带有私钥的助手来访问值:
type reqKey int
const key reqKey=iota
type RequestData struct {
UserID uuid.UUID
Now time.Time
}
func ContextWithRequest(ctx context.Context,req requestData) context.Context {
return context.WithValue(ctx,key,req)
}
func GetRequest(ctx context) RequestData {
x:=ctx.Value(key)
if x!=nil {
return x.(RequestData)
}
return RequestData{}
}
当然,如果要更改RequestData
,则需要添加指向上下文的指针。
推荐阅读
- python - 使用python从xml文件中提取数据时出错
- java - REST Web 服务中的 spring 安全性
- rstudio - 动态设置PDF输出名称离子Rmarkdown
- google-cloud-platform - 无法在澳大利亚区域启动 Composer env:“INVALID_ARGUMENT:意外位置:australia-southeast1”
- logging - 打开访客网络流量监视器 OS X
- automapper - 将 int (Id) 映射到 Model 实例
- c# - .NET WebApi - 如何接收带有附加参数的文件?
- svgpanzoom - 如何在 SVG PanZoom 中添加动画
- asp.net - 在 mvc 中执行操作之前的所有操作中的默认参数
- testing - 如何使用开源 testcafe 编写参数化测试?