1
0
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:
Gerasimos (Makis) Maropoulos
2017-01-02 21:20:17 +02:00
parent ced2083ab3
commit 8bbd9f8fc5
25 changed files with 2067 additions and 2213 deletions

View File

@@ -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)
})
}