Our proxy configuration was historically incorrect, due to which a lot of customers have that in their setups. As a result, strictly following the websocket RFC results in a breaking change. For now, we transparently upgrade the version header to 1.1, if we detect 1.0. If a client was sending 1.0, it wouldn't have worked anyways because persistent connections were introduced from 1.1 onwards. https://mattermost.atlassian.net/browse/MM-33836 ```release-note WebSocket handshakes done with HTTP version lower than 1.1 will result in a warning, and the server will transparently upgrade the version to 1.1 to comply with the websocket RFC. This is done to work around incorrect nginx (and other proxy) configs that do not set the proxy_http_version directive to 1.1. This facility will be removed in a future Mattermost version and it is strongly recommended to fix the proxy configuration to correctly use the websocket protocol. ``` Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
58 строки
1.7 KiB
Go
58 строки
1.7 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
package api4
|
|
|
|
import (
|
|
"net/http"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/gobwas/ws"
|
|
|
|
"github.com/mattermost/mattermost-server/v5/model"
|
|
"github.com/mattermost/mattermost-server/v5/shared/mlog"
|
|
)
|
|
|
|
func (api *API) InitWebSocket() {
|
|
// Optionally supports a trailing slash
|
|
api.BaseRoutes.ApiRoot.Handle("/{websocket:websocket(?:\\/)?}", api.ApiHandlerTrustRequester(connectWebSocket)).Methods("GET")
|
|
}
|
|
|
|
func connectWebSocket(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
fn := c.App.OriginChecker()
|
|
if fn != nil && !fn(r) {
|
|
c.Err = model.NewAppError("origin_check", "api.web_socket.connect.check_origin.app_error", nil, "", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
upgrader := ws.HTTPUpgrader{
|
|
Timeout: 5 * time.Second,
|
|
}
|
|
|
|
// Uprgade the HTTP version header to 1.1, if we detect a 1.0 header.
|
|
// This is a hack to work around a flaw in our proxy configs which sends the protocol version as 1.0.
|
|
// It will be removed in a future version.
|
|
if r.ProtoMajor == 1 && r.ProtoMinor == 0 {
|
|
r.ProtoMinor = 1
|
|
mlog.Warn("The HTTP version field was detected as 1.0 during WebSocket handshake. This is most probably due to an incorrect proxy configuration. Please upgrade your proxy config to set the header version to a minimum of 1.1.")
|
|
}
|
|
|
|
conn, _, _, err := upgrader.Upgrade(r, w)
|
|
if err != nil {
|
|
c.Err = model.NewAppError("connect", "api.web_socket.connect.upgrade.app_error", nil, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
wc := c.App.NewWebConn(conn, *c.App.Session(), c.App.T, "")
|
|
if c.App.Session().UserId != "" {
|
|
c.App.HubRegister(wc)
|
|
}
|
|
|
|
if runtime.GOOS == "windows" {
|
|
wc.BlockingPump()
|
|
} else {
|
|
go wc.Pump()
|
|
}
|
|
}
|