mirror of
https://github.com/kataras/iris.git
synced 2026-03-04 07:26:37 +00:00
Happy new year! Update to 6.0.0 | HTTP/2 full support. https://github.com/kataras/iris/issues/565
full commit from development branch. Examples, book, middleware, plugins are updated to the latest iris version. Read HISTORY.md for more. The 'old' v5 branch which relied on fasthttp exists for those who want to use it navigate there: https://github.com/kataras/iris/tree/5.0.0
This commit is contained in:
135
websocket.go
135
websocket.go
@@ -1,7 +1,9 @@
|
||||
package iris
|
||||
|
||||
import (
|
||||
irisWebsocket "github.com/iris-contrib/websocket"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/kataras/go-websocket"
|
||||
)
|
||||
|
||||
@@ -22,85 +24,52 @@ type (
|
||||
// the below code is a wrapper and bridge between iris-contrib/websocket and kataras/go-websocket
|
||||
WebsocketServer struct {
|
||||
websocket.Server
|
||||
upgrader irisWebsocket.Upgrader
|
||||
|
||||
// the only fields we need at runtime here for iris-specific error and check origin funcs
|
||||
// they comes from WebsocketConfiguration
|
||||
|
||||
// Error specifies the function for generating HTTP error responses.
|
||||
Error func(ctx *Context, status int, reason string)
|
||||
// CheckOrigin returns true if the request Origin header is acceptable. If
|
||||
// CheckOrigin is nil, the host in the Origin header must not be set or
|
||||
// must match the host of the request.
|
||||
CheckOrigin func(ctx *Context) bool
|
||||
station *Framework
|
||||
once sync.Once
|
||||
// Config:
|
||||
// if endpoint is not empty then this configuration is used instead of the station's
|
||||
// useful when the user/dev wants more than one websocket server inside one iris instance.
|
||||
Config WebsocketConfiguration
|
||||
}
|
||||
)
|
||||
|
||||
// NewWebsocketServer returns an empty WebsocketServer, nothing special here.
|
||||
func NewWebsocketServer() *WebsocketServer {
|
||||
return &WebsocketServer{}
|
||||
// NewWebsocketServer returns a new empty unitialized websocket server
|
||||
// it runs on first OnConnection
|
||||
func NewWebsocketServer(station *Framework) *WebsocketServer {
|
||||
return &WebsocketServer{station: station, Server: websocket.New()}
|
||||
}
|
||||
|
||||
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
|
||||
//
|
||||
// The responseHeader is included in the response to the client's upgrade
|
||||
// request. Use the responseHeader to specify cookies (Set-Cookie) and the
|
||||
// application negotiated subprotocol (Sec-Websocket-Protocol).
|
||||
//
|
||||
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
|
||||
// response.
|
||||
func (s *WebsocketServer) Upgrade(ctx *Context) error {
|
||||
return s.upgrader.Upgrade(ctx.RequestCtx)
|
||||
}
|
||||
// NewWebsocketServer creates the client side source route and the route path Endpoint with the correct Handler
|
||||
// receives the websocket configuration and the iris station
|
||||
// and returns the websocket server which can be attached to more than one iris station (if needed)
|
||||
func (ws *WebsocketServer) init() {
|
||||
if ws.Config.Endpoint == "" {
|
||||
ws.Config = ws.station.Config.Websocket
|
||||
}
|
||||
|
||||
// Handler is the iris Handler to upgrade the request
|
||||
// used inside RegisterRoutes
|
||||
func (s *WebsocketServer) Handler(ctx *Context) {
|
||||
// first, check origin
|
||||
if !s.CheckOrigin(ctx) {
|
||||
s.Error(ctx, StatusForbidden, "websocket: origin not allowed")
|
||||
c := ws.Config
|
||||
|
||||
if c.Endpoint == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// all other errors comes from the underline iris-contrib/websocket
|
||||
if err := s.Upgrade(ctx); err != nil {
|
||||
if ctx.framework.Config.IsDevelopment {
|
||||
ctx.Log("Websocket error while trying to Upgrade the connection. Trace: %s", err.Error())
|
||||
}
|
||||
|
||||
statusErrCode := StatusBadRequest
|
||||
if herr, isHandshake := err.(irisWebsocket.HandshakeError); isHandshake {
|
||||
statusErrCode = herr.Status()
|
||||
}
|
||||
// if not handshake error just fire the custom(if any) StatusBadRequest
|
||||
// with the websocket's error message in the ctx.Get("WsError")
|
||||
DefaultWebsocketError(ctx, statusErrCode, err.Error())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterTo creates the client side source route and the route path Endpoint with the correct Handler
|
||||
// receives the websocket configuration and the iris station
|
||||
func (s *WebsocketServer) RegisterTo(station *Framework, c WebsocketConfiguration) {
|
||||
|
||||
// Note: s.Server should be initialize on the first OnConnection, which is called before this func when Default websocket server.
|
||||
// When not: when calling this function before OnConnection, when we have more than one websocket server running
|
||||
if s.Server == nil {
|
||||
s.Server = websocket.New()
|
||||
}
|
||||
// is just a conversional type for kataras/go-websocket.Connection
|
||||
s.upgrader = irisWebsocket.Custom(s.Server.HandleConnection, c.ReadBufferSize, c.WriteBufferSize, c.Headers)
|
||||
|
||||
// set the routing for client-side source (javascript) (optional)
|
||||
clientSideLookupName := "iris-websocket-client-side"
|
||||
station.Get(c.Endpoint, s.Handler)
|
||||
ws.station.Get(c.Endpoint, ToHandler(ws.Server.Handler()))
|
||||
// check if client side already exists
|
||||
if station.Lookup(clientSideLookupName) == nil {
|
||||
if ws.station.Lookup(clientSideLookupName) == nil {
|
||||
// serve the client side on domain:port/iris-ws.js
|
||||
station.StaticContent("/iris-ws.js", contentJavascript, websocket.ClientSource)(clientSideLookupName)
|
||||
ws.station.StaticContent("/iris-ws.js", contentJavascript, websocket.ClientSource)(clientSideLookupName)
|
||||
}
|
||||
|
||||
s.Server.Set(websocket.Config{
|
||||
if c.CheckOrigin == nil {
|
||||
c.CheckOrigin = DefaultWebsocketCheckOrigin
|
||||
}
|
||||
|
||||
if c.Error == nil {
|
||||
c.Error = DefaultWebsocketError
|
||||
}
|
||||
// set the underline websocket server's configuration
|
||||
ws.Server.Set(websocket.Config{
|
||||
WriteTimeout: c.WriteTimeout,
|
||||
PongTimeout: c.PongTimeout,
|
||||
PingPeriod: c.PingPeriod,
|
||||
@@ -108,22 +77,13 @@ func (s *WebsocketServer) RegisterTo(station *Framework, c WebsocketConfiguratio
|
||||
BinaryMessages: c.BinaryMessages,
|
||||
ReadBufferSize: c.ReadBufferSize,
|
||||
WriteBufferSize: c.WriteBufferSize,
|
||||
Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) {
|
||||
ctx := ws.station.AcquireCtx(w, r)
|
||||
c.Error(ctx, status, reason)
|
||||
ws.station.ReleaseCtx(ctx)
|
||||
},
|
||||
CheckOrigin: c.CheckOrigin,
|
||||
})
|
||||
|
||||
s.Error = c.Error
|
||||
s.CheckOrigin = c.CheckOrigin
|
||||
|
||||
if s.Error == nil {
|
||||
s.Error = DefaultWebsocketError
|
||||
}
|
||||
|
||||
if s.CheckOrigin == nil {
|
||||
s.CheckOrigin = DefaultWebsocketCheckOrigin
|
||||
}
|
||||
|
||||
// run the ws server
|
||||
s.Server.Serve()
|
||||
|
||||
}
|
||||
|
||||
// WebsocketConnection is the front-end API that you will use to communicate with the client side
|
||||
@@ -132,15 +92,10 @@ type WebsocketConnection interface {
|
||||
}
|
||||
|
||||
// OnConnection this is the main event you, as developer, will work with each of the websocket connections
|
||||
func (s *WebsocketServer) OnConnection(connectionListener func(WebsocketConnection)) {
|
||||
if s.Server == nil {
|
||||
// for default webserver this is the time when the websocket server will be init
|
||||
// let's initialize here the ws server, the user/dev is free to change its config before this step.
|
||||
s.Server = websocket.New() // we need that in order to use the Iris' WebsocketConnnection, which
|
||||
// config is empty here because are setted on the RegisterTo
|
||||
// websocket's configuration is optional on New because it doesn't really used before the websocket.Serve
|
||||
}
|
||||
s.Server.OnConnection(func(c websocket.Connection) {
|
||||
func (ws *WebsocketServer) OnConnection(connectionListener func(WebsocketConnection)) {
|
||||
ws.once.Do(ws.init)
|
||||
|
||||
ws.Server.OnConnection(func(c websocket.Connection) {
|
||||
connectionListener(c)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user