2017-07-10 11:54:40 +00:00
|
|
|
package websocket
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
uuid "github.com/satori/go.uuid"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// DefaultWriteTimeout is default value of Write Timeout
|
|
|
|
DefaultWriteTimeout = 0
|
|
|
|
// DefaultReadTimeout is default value of Read Timeout
|
|
|
|
DefaultReadTimeout = 0
|
|
|
|
// DefaultPongTimeout is default value of Pong Timeout
|
|
|
|
DefaultPongTimeout = 60 * time.Second
|
|
|
|
// DefaultPingPeriod is default value of Ping Period
|
|
|
|
DefaultPingPeriod = (DefaultPongTimeout * 9) / 10
|
|
|
|
// DefaultMaxMessageSize is default value of Max Message Size
|
|
|
|
DefaultMaxMessageSize = 1024
|
|
|
|
// DefaultReadBufferSize is default value of Read Buffer Size
|
|
|
|
DefaultReadBufferSize = 4096
|
|
|
|
// DefaultWriteBufferSize is default value of Write Buffer Size
|
|
|
|
DefaultWriteBufferSize = 4096
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// DefaultIDGenerator returns the UUID of the client
|
|
|
|
DefaultIDGenerator = func(*http.Request) string { return uuid.NewV4().String() }
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// OptionSetter sets a configuration field to the websocket config
|
|
|
|
// used to help developers to write less and configure only what they really want and nothing else
|
|
|
|
OptionSetter interface {
|
2017-07-11 08:05:06 +00:00
|
|
|
Set(o *Options)
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// OptionSet implements the OptionSetter
|
2017-07-11 08:05:06 +00:00
|
|
|
OptionSet func(o *Options)
|
2017-07-10 11:54:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Set is the func which makes the OptionSet an OptionSetter, this is used mostly
|
2017-07-11 08:05:06 +00:00
|
|
|
func (os OptionSet) Set(o *Options) {
|
|
|
|
os(o)
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
// Options is configuration of the websocket server
|
|
|
|
type Options struct {
|
2017-07-10 11:54:40 +00:00
|
|
|
Error func(res http.ResponseWriter, req *http.Request, status int, reason error)
|
|
|
|
CheckOrigin func(req *http.Request) bool
|
|
|
|
WriteTimeout time.Duration
|
|
|
|
ReadTimeout time.Duration
|
|
|
|
PongTimeout time.Duration
|
|
|
|
PingPeriod time.Duration
|
|
|
|
MaxMessageSize int64
|
|
|
|
BinaryMessages bool
|
|
|
|
ReadBufferSize int
|
|
|
|
WriteBufferSize int
|
|
|
|
IDGenerator func(*http.Request) string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set is the func which makes the OptionSet an OptionSetter, this is used mostly
|
2017-07-11 08:05:06 +00:00
|
|
|
func (o *Options) Set(main *Options) {
|
|
|
|
main.Error = o.Error
|
|
|
|
main.CheckOrigin = o.CheckOrigin
|
|
|
|
main.WriteTimeout = o.WriteTimeout
|
|
|
|
main.ReadTimeout = o.ReadTimeout
|
|
|
|
main.PongTimeout = o.PongTimeout
|
|
|
|
main.PingPeriod = o.PingPeriod
|
|
|
|
main.MaxMessageSize = o.MaxMessageSize
|
|
|
|
main.BinaryMessages = o.BinaryMessages
|
|
|
|
main.ReadBufferSize = o.ReadBufferSize
|
|
|
|
main.WriteBufferSize = o.WriteBufferSize
|
|
|
|
main.IDGenerator = o.IDGenerator
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Error sets the error handler
|
|
|
|
func Error(val func(res http.ResponseWriter, req *http.Request, status int, reason error)) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Error = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckOrigin sets a handler which will check if different origin(domains) are allowed to contact with
|
|
|
|
// the websocket server
|
|
|
|
func CheckOrigin(val func(req *http.Request) bool) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.CheckOrigin = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteTimeout time allowed to write a message to the connection.
|
|
|
|
// Default value is 15 * time.Second
|
|
|
|
func WriteTimeout(val time.Duration) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.WriteTimeout = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadTimeout time allowed to read a message from the connection.
|
|
|
|
// Default value is 15 * time.Second
|
|
|
|
func ReadTimeout(val time.Duration) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.ReadTimeout = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PongTimeout allowed to read the next pong message from the connection
|
|
|
|
// Default value is 60 * time.Second
|
|
|
|
func PongTimeout(val time.Duration) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.PongTimeout = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout
|
|
|
|
// Default value is (PongTimeout * 9) / 10
|
|
|
|
func PingPeriod(val time.Duration) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.PingPeriod = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MaxMessageSize max message size allowed from connection
|
|
|
|
// Default value is 1024
|
|
|
|
func MaxMessageSize(val int64) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.MaxMessageSize = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// BinaryMessages set it to true in order to denotes binary data messages instead of utf-8 text
|
|
|
|
// compatible if you wanna use the Connection's EmitMessage to send a custom binary data to the client,
|
|
|
|
// like a native server-client communication.
|
|
|
|
// defaults to false
|
|
|
|
func BinaryMessages(val bool) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.BinaryMessages = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadBufferSize is the buffer size for the underline reader
|
|
|
|
func ReadBufferSize(val int) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.ReadBufferSize = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteBufferSize is the buffer size for the underline writer
|
|
|
|
func WriteBufferSize(val int) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.WriteBufferSize = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IDGenerator used to create (and later on, set)
|
|
|
|
// an ID for each incoming websocket connections (clients).
|
|
|
|
// The request is an argument which you can use to generate the ID (from headers for example).
|
|
|
|
// If empty then the ID is generated by func: uuid.NewV4().String()
|
|
|
|
func IDGenerator(val func(*http.Request) string) OptionSet {
|
2017-07-11 08:05:06 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.IDGenerator = val
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate validates the configuration
|
2017-07-11 08:05:06 +00:00
|
|
|
func (o *Options) Validate() {
|
2017-07-10 11:54:40 +00:00
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.WriteTimeout < 0 {
|
|
|
|
o.WriteTimeout = DefaultWriteTimeout
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.ReadTimeout < 0 {
|
|
|
|
o.ReadTimeout = DefaultReadTimeout
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.PongTimeout < 0 {
|
|
|
|
o.PongTimeout = DefaultPongTimeout
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.PingPeriod <= 0 {
|
|
|
|
o.PingPeriod = DefaultPingPeriod
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.MaxMessageSize <= 0 {
|
|
|
|
o.MaxMessageSize = DefaultMaxMessageSize
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.ReadBufferSize <= 0 {
|
|
|
|
o.ReadBufferSize = DefaultReadBufferSize
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.WriteBufferSize <= 0 {
|
|
|
|
o.WriteBufferSize = DefaultWriteBufferSize
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.Error == nil {
|
|
|
|
o.Error = func(res http.ResponseWriter, req *http.Request, status int, reason error) {
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.CheckOrigin == nil {
|
|
|
|
o.CheckOrigin = func(req *http.Request) bool {
|
2017-07-10 11:54:40 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-11 08:05:06 +00:00
|
|
|
if o.IDGenerator == nil {
|
|
|
|
o.IDGenerator = DefaultIDGenerator
|
2017-07-10 11:54:40 +00:00
|
|
|
}
|
|
|
|
}
|