最近将Go Webapp中优秀的alexedwards/scs/v2从2.5.0升级到2.7.0,以允许Go 1.20+支持HTTP.NewResponseController().随后允许为大型文件上传延长处理程序特定的服务器写入超时.这个不错. 这一必要升级的一个不幸后果是失go 了WebSocket功能,目前使用的是Gorilla WebSockets v1.5.1(最新版本).我收到在try 连接升级时产生的常见错误... websocket: response does not implement http.Hijacker个 我已经研究了这件事的几条线索,这里有几条线索,但我还不能解决任何与此案相关的问题. 我已经try 了几次在我的其他中间件代码和我的WebSocket端点处理程序中实现Http.Hijacker(注释掉了,为了说明而附上了‘被误导的’例子)……我只是觉得我不太明白这一点.

type WebsocketConnection struct {
    *websocket.Conn
}

type WebsocketPayload struct {
    Action      string              `json:"action"`
    Message     string              `json:"message"`
    AdminName   string              `json:"admin_name"`
    MessageType string              `json:"message_type"`
    AdminID     int                 `json:"admin_id"`
    Connection  WebsocketConnection `json:"-"`
}

type WebsocketJSONResponse struct {
    Action        string   `json:"action"`
    Message       string   `json:"message"`
    AdminName     string   `json:"admin_name"`
    AdminID       int      `json:"admin_id"`
    CurrentLogins []string `json:"current_logins"`
}

var upgradeConnection = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin:     func(r *http.Request) bool { return true },
}

var webClients = make(map[WebsocketConnection]string)

var websocketChannel = make(chan WebsocketPayload)

func (app *application) WebsocketEndPoint(w http.ResponseWriter, r *http.Request) {
    // rc := http.NewResponseController(w)
    // netConn, _, err := rc.Hijack()
    // if err != nil {
    //  app.errorLog.Println(err)
    //  return
    // }
    // defer netConn.Close()

    app.debugLog.Printf("w's type is %T\n", w)

    ws, err := upgradeConnection.Upgrade(w, r, nil)
    if err != nil {
        app.errorLog.Println(err)  <= ERROR HERE
        return
    }

    app.infoLog.Printf("Web client connected from %s", r.RemoteAddr)
    var response WebsocketJSONResponse
    response.Message = "Connected to server..."

    err = ws.WriteJSON(response)
    if err != nil {
        app.errorLog.Println(err)
        return
    }

    conn := WebsocketConnection{Conn: ws}
    webClients[conn] = ""

    go app.ListenForWebsocket(&conn)
}

本例中的"w"是*scs.essionResponseWriter. 如何在不 destruct 连接的情况下在响应中实现Http.Hijacker并进行升级?请问正确的方法是什么?

推荐答案

alexedwards/scs/v2包supports the Hijacker interface的版本2.5.0. 版本2.7.0不支持Hijacker接口,但支持support response controllers. gorilla websocket包does not使用响应控制器.

Option 1

使用alexedwards/scs/v2包的2.5.0.

Option 2

通过在您的应用程序代码中解开响应编写器来解决Gorilla包的缺陷:

func (app *application) WebsocketEndPoint(w http.ResponseWriter, r *http.Request) {

    wupgrade := w
    if u, ok := w.(interface{ Unwrap() http.ResponseWriter }); ok {
        wupgrade = u.Unwrap()
    }

    app.debugLog.Printf("w's type is %T\n", w)

    ws, err := upgradeConnection.Upgrade(wupgrade, r, nil)
    if err != nil {
        app.errorLog.Println(err)
        return
    }

    app.infoLog.Printf("Web client connected from %s", r.RemoteAddr)
    var response WebsocketJSONResponse
    response.Message = "Connected to server..."

    err = ws.WriteJSON(response)
    if err != nil {
        app.errorLog.Println(err)
        return
    }

    conn := WebsocketConnection{Conn: ws}
    webClients[conn] = ""

    go app.ListenForWebsocket(&conn)
}

Go相关问答推荐

使用Gorm创建自定义连接表

编辑时保留YAML文件中的单引号

如何使用我的 struct 化日志(log)记录格式使人panic ?

Go Colly-访问for循环中的URL

在整个SQL事务中将使用上下文作为默认设置吗?

在Go中旋转矩阵

Prometheus 摘要分位数错误

在 go 中,将接收器 struct 从值更改为指针是否向后兼容?

如何将字节文件高效地读入int64切片?

linter 警告:返回值被忽略

使用 unsafe.Pointer 将 struct point直接转换为另一个 struct 是否安全?

如何在没有内存分配的情况下压缩和发布文件

在 GORM 中,如何在特定时区配置 autoCreateTime 和 autoUpdateTime?

Golang ACMEv2 HTTP-01 挑战不挑战服务器

出于某种原因,Golang (Go) AES CBC 密文被填充了 16 个 0x00 字节

实现接口的指针的泛型类型是什么?

Go/Golang:如何从 big.Float 中提取最低有效数字?

带有 *s3.S3 对象的 Golang 单元测试

Go 错误处理、类型断言和 net package包

为什么 Go 的构造函数要返回地址?