登录
首页 >  Golang >  Go问答

中间件中实现http.Hijacker的方法

来源:stackoverflow

时间:2024-03-27 09:30:24 122浏览 收藏

在中间件中实现 HTTP 劫持器时遇到困难。由于中间件阻止了 WS 响应劫持器,WebSocket 连接无法建立。通过覆写 writer 的 Hijack 和 Flush 方法,在最小程度地调整数据结构后,使用 WebSocket 和日志记录中间件成为可能。

问题内容

我尝试在我的 restful web 服务器中添加 websocket,但是(可能)由于中间件阻止了 ws 响应劫持者,它无法成功建立连接。

// main.go
api := http.Server{
    ...
    Handler:      handlers.API(middleware...), // pass the needed middleware.
}

// handler.go
func API(middleware...) http.Handler {
    app := web.NewApp(middleware...)
    app.Handle(http.MethodGet, "/ws", wsHandler)
}
func wsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
    upgrader.CheckOrigin = func(r *http.Request) bool {
        return true
    }

    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        return errors.Wrapf(err, "")
    }
    defer conn.Close()

    for {
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            ...
            return web.NewRequestError(err, http.StatusInternalServerError)
        }

        ...
    }

}

// web.go
type Handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) error
type Middleware func(Handler) Handler
func (a *App) Handle(method, path string, handler Handler, mw ...Middleware) {
    handler = wrapMiddleware(mw, handler)
    ...
}
func wrapMiddleware(mw []Middleware, handler Handler) Handler {
    for i := len(mw) - 1; i >= 0; i-- {
        h := mw[i]
        if h != nil {
            handler = h(handler)
        }
    }

    return handler
}

解决方案


我发现 http://www.inanzzz.com/index.php/post/q7bs/access-log-middleware-in-golang 中的这个示例非常有用:

// Overrides http.Hijacker type.
func (w *writer) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    hj, ok := w.ResponseWriter.(http.Hijacker)
    if !ok {
        return nil, nil, fmt.Errorf("the hijacker interface is not supported")
    }
 
    return hj.Hijack()
}

// Overrides http.Flusher type.
func (w *writer) Flush() {
    if fl, ok := w.ResponseWriter.(http.Flusher); ok {
        if w.resStatus == 0 {
            w.WriteHeader(http.StatusOK)
        }
 
        fl.Flush()
    }
}

对我的数据结构进行最小程度的调整后,我仍然能够使用我的 websocket 和我从 so 一起复制的日志记录中间件。

今天关于《中间件中实现http.Hijacker的方法》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>