首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将数据从中间件传递到处理程序?

如何将数据从中间件传递到处理程序?
EN

Stack Overflow用户
提问于 2015-07-20 02:22:53
回答 3查看 11.7K关注 0票数 20

我正在设计我的处理程序来返回一个http.Handler。下面是我的处理程序的设计:

代码语言:javascript
运行
复制
 func Handler() http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  })
}

我的中间件被设计为接受http.Handler,然后在中间件完成其操作后调用处理程序。下面是我的中间件的设计:

代码语言:javascript
运行
复制
 func Middleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // Middleware operations

    next.ServeHTTP(w, r)
  })
}

考虑到我的中间件和处理程序的设计,将信息从中间件传递到处理程序的正确方法是什么?我试图从中间件向处理程序传递的信息是从请求正文解析的JSON web令牌。如果我没有将解析的JWT传递给处理程序,那么我将需要在处理程序中再次解析JWT。在中间件和处理程序中解析JWT的请求正文似乎很浪费。如果这些信息是相关的,我使用标准的net/http库和gorilla mux。

EN

回答 3

Stack Overflow用户

发布于 2015-07-21 23:02:32

既然您已经在使用Gorilla,那么就来看一下context包。

(如果您不想更改方法签名,这很好。)

代码语言:javascript
运行
复制
import (
    "github.com/gorilla/context"
)

...

func Middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Middleware operations
        // Parse body/get token.
        context.Set(r, "token", token)

        next.ServeHTTP(w, r)
    })
}

...

func Handler() http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := context.Get(r, "token")
    })
}

更新

Gorilla context包现在处于维护模式

根据回购:

注意,gorilla/context早在context.Context出现之前就已经诞生了,它不能很好地处理http.Request.WithContext (添加到net/http Go 1.7之后)执行的请求的浅层复制。

在这些情况下,使用gorilla/context可能会导致内存泄漏,因为指向每个http.Request的指针变得“孤立”,并且在发送响应时不会被清除。

你应该在Go 1.7中使用http.Request.Context()特性。

票数 21
EN

Stack Overflow用户

发布于 2017-03-19 00:43:28

传递请求作用域数据的正确方法现在应该是标准库中的上下文包。

https://golang.org/pkg/context/

您可以在http.Request上使用request.Context访问它。

票数 8
EN

Stack Overflow用户

发布于 2015-07-20 02:28:49

第一种方法,类似于这个问题,在Davedcodemodus/chain中。

包链有助于处理程序包装链的组合,这些处理程序包装链携带请求范围的数据。

它使用notion of Context,再加上上下文处理程序:

代码语言:javascript
运行
复制
func ctxHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
    // ...

    if s, ok := getMyString(ctx); ok {
        // s = "Send this down the line."
    }

    // ...
}

另一种方法:你可以看看Matt Silverlock (elithrar)写的"Custom Handlers and Avoiding Globals in Go Web Applications“。(full example here)

其思想是在包含相关上下文的类型上定义ServeHTTP

代码语言:javascript
运行
复制
// We've turned our original appHandler into a struct with two fields:
// - A function type similar to our original handler type (but that now takes an *appContext)
// - An embedded field of type *appContext
type appHandler struct {
    *appContext
    h func(*appContext, http.ResponseWriter, *http.Request) (int, error)
}

// Our ServeHTTP method is mostly the same, and also has the ability to
// access our *appContext's fields (templates, loggers, etc.) as well.
func (ah appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // Updated to pass ah.appContext as a parameter to our handler type.
    status, err := ah.h(ah.appContext, w, r)
    if err != nil {
        log.Printf("HTTP %d: %q", status, err)
        switch status {
        case http.StatusNotFound:
            http.NotFound(w, r)
            // And if we wanted a friendlier error page, we can
            // now leverage our context instance - e.g.
            // err := ah.renderTemplate(w, "http_404.tmpl", nil)
        case http.StatusInternalServerError:
            http.Error(w, http.StatusText(status), status)
        default:
            http.Error(w, http.StatusText(status), status)
        }
    }
}

appContext结构中,可以放入任何想要传递的数据。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31504456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档