update websocket examples - keep neffos and use the iris/websocket as helper only

Former-commit-id: c34b916e186286cd0de6d694d8bdb4f9390121a2
This commit is contained in:
Gerasimos (Makis) Maropoulos 2019-07-01 18:52:17 +03:00
parent 69171e844d
commit 35389c6ef8
14 changed files with 40 additions and 10806 deletions

View File

@ -477,7 +477,9 @@ iris session manager lives on its own [package](https://github.com/kataras/iris/
### Websockets ### Websockets
iris websocket library lives on its own [package](https://github.com/kataras/iris/tree/master/websocket) which depends on the [kataras/neffos](https://github.com/kataras/neffos) external package. [WebSocket](https://wikipedia.org/wiki/WebSocket) is a protocol that enables two-way persistent communication channels over TCP connections. It is used for applications such as chat, stock tickers, games, anywhere you want real-time functionality in a web application.
Iris websocket library is now merged with the [neffos real-time framework](https://github.com/kataras/neffos) and Iris-specific helpers live on the [iris/websocket](https://github.com/kataras/iris/tree/master/websocket) subpackage. Learn neffos from its [wiki](https://github.com/kataras/neffos#learning-neffos) and have a look some of the [Iris websocket examples](websocket/).
The package is designed to work with raw websockets although its API is similar to the famous [socket.io](https://socket.io). I have read an article recently and I felt very contented about my decision to design a **fast** websocket-**only** package for Iris and not a backwards socket.io-like package. You can read that article by following this link: https://medium.com/@ivanderbyl/why-you-don-t-need-socket-io-6848f1c871cd. The package is designed to work with raw websockets although its API is similar to the famous [socket.io](https://socket.io). I have read an article recently and I felt very contented about my decision to design a **fast** websocket-**only** package for Iris and not a backwards socket.io-like package. You can read that article by following this link: https://medium.com/@ivanderbyl/why-you-don-t-need-socket-io-6848f1c871cd.
@ -486,13 +488,8 @@ The package is designed to work with raw websockets although its API is similar
* [Go Client](websocket/basic/go-client/client.go) * [Go Client](websocket/basic/go-client/client.go)
* [Browser Client](websocket/basic/browser/index.html) * [Browser Client](websocket/basic/browser/index.html)
* [Browser NPM Client (browserify)](websocket/basic/browserify/app.js) * [Browser NPM Client (browserify)](websocket/basic/browserify/app.js)
- [Native Messages](websocket/native-messages/main.go) - [Native Messages](websocket/native-messages/main.go) **UPDATED**
- [Connection List](websocket/connectionlist/main.go) - [TLS Enabled](websocket/secure/README.md)
- [TLS Enabled](websocket/secure/main.go)
- [Custom Raw Go Client](websocket/custom-go-client/main.go)
- [Third-Party socket.io](websocket/third-party-socketio/main.go)
> You're free to use your own favourite websockets package if you'd like so.
### Typescript Automation Tools ### Typescript Automation Tools

View File

@ -425,23 +425,13 @@ Iris session 管理独立包 [package](https://github.com/kataras/iris/tree/mast
### Websockets ### Websockets
iris websocket库依赖于它自己的[包](https://github.com/kataras/iris/tree/master/websocket).
设计这个包的目的是处理原始websockets虽然它的API和著名的[socket.io](https://socket.io)很像。我最近读了一片文章,并且对我
决定给iris设计一个**快速的**websocket**限定**包并且不是一个向后传递类socket.io的包。你可以阅读这个链接里的文章https://medium.com/@ivanderbyl/why-you-don-t-need-socket-io-6848f1c871cd。
- [Basic](websocket/basic) **新** - [Basic](websocket/basic) **新**
* [Server](websocket/basic/server.go) * [Server](websocket/basic/server.go)
* [Go Client](websocket/basic/go-client/client.go) * [Go Client](websocket/basic/go-client/client.go)
* [Browser Client](websocket/basic/browser/index.html) * [Browser Client](websocket/basic/browser/index.html)
* [Browser NPM Client (browserify)](websocket/basic/browserify/app.js) * [Browser NPM Client (browserify)](websocket/basic/browserify/app.js)
- [原生消息](websocket/native-messages/main.go) - [原生消息](websocket/native-messages/main.go) **更新**
- [连接列表](websocket/connectionlist/main.go) - [TLS支持](websocket/secure/README.md)
- [TLS支持](websocket/secure/main.go)
- [自定义原始Go客户端](websocket/custom-go-client/main.go)
- [第三方socket.io](websocket/third-party-socketio/main.go)
> 如果你愿意你可以自由使用你自己喜欢的websockets包。
### Typescript 自动化工具 ### Typescript 自动化工具

View File

@ -1,135 +0,0 @@
# Websocket
[WebSocket](https://wikipedia.org/wiki/WebSocket) is a protocol that enables two-way persistent communication channels over TCP connections. It is used for applications such as chat, stock tickers, games, anywhere you want real-time functionality in a web application.
[View or download sample code](https://github.com/kataras/iris/tree/master/_examples/websocket).
## When to use it
Use WebSockets when you need to work directly with a socket connection. For example, you might need the best possible performance for a real-time game.
## How to use it
* import the `"github.com/kataras/iris/websocket"`
* Configure the websocket package.
* Accept WebSocket requests.
* Send and receive messages.
### Import the websocket package
```go
import "github.com/kataras/iris/websocket"
```
### Configure the websocket package
```go
import "github.com/kataras/iris/websocket"
func main() {
ws := websocket.New(websocket.Config{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
})
}
```
#### Complete configuration
```go
// Config the websocket server configuration
// all of these are optional.
type Config struct {
// 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 DefaultIDGenerator: randomString(64)
IDGenerator func(ctx context.Context) string
// Error is the function that will be fired if any client couldn't upgrade the HTTP connection
// to a websocket connection, a handshake error.
Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
// CheckOrigin a function that is called right before the handshake,
// if returns false then that client is not allowed to connect with the websocket server.
CheckOrigin func(r *http.Request) bool
// HandshakeTimeout specifies the duration for the handshake to complete.
HandshakeTimeout time.Duration
// WriteTimeout time allowed to write a message to the connection.
// 0 means no timeout.
// Default value is 0
WriteTimeout time.Duration
// ReadTimeout time allowed to read a message from the connection.
// 0 means no timeout.
// Default value is 0
ReadTimeout time.Duration
// PongTimeout allowed to read the next pong message from the connection.
// Default value is 60 * time.Second
PongTimeout time.Duration
// PingPeriod send ping messages to the connection with this period. Must be less than PongTimeout.
// Default value is 60 *time.Second
PingPeriod time.Duration
// MaxMessageSize max message size allowed from connection.
// Default value is 1024
MaxMessageSize int64
// 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
BinaryMessages bool
// ReadBufferSize is the buffer size for the underline reader
// Default value is 4096
ReadBufferSize int
// WriteBufferSize is the buffer size for the underline writer
// Default value is 4096
WriteBufferSize int
// EnableCompression specify if the server should attempt to negotiate per
// message compression (RFC 7692). Setting this value to true does not
// guarantee that compression will be supported. Currently only "no context
// takeover" modes are supported.
EnableCompression bool
// Subprotocols specifies the server's supported protocols in order of
// preference. If this field is set, then the Upgrade method negotiates a
// subprotocol by selecting the first match in this list with a protocol
// requested by the client.
Subprotocols []string
}
```
### Accept WebSocket requests & send & receive messages
```go
import (
"github.com/kataras/iris"
"github.com/kataras/iris/websocket"
)
func main() {
ws := websocket.New(websocket.Config{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
})
ws.OnConnection(handleConnection)
app := iris.New()
// register the server on an endpoint.
// see the inline javascript code in the websockets.html, this endpoint is used to connect to the server.
app.Get("/echo", ws.Handler())
// serve the javascript builtin client-side library,
// see websockets.html script tags, this path is used.
app.Any("/iris-ws.js", func(ctx iris.Context) {
ctx.Write(websocket.ClientSource)
})
}
func handleConnection(c websocket.Connection) {
// Read events from browser
c.On("chat", func(msg string) {
// Print the message to the console, c.Context() is the iris's http context.
fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg)
// Write message back to the client message owner:
// c.Emit("chat", msg)
c.To(websocket.Broadcast).Emit("chat", msg)
})
}
```

View File

@ -10,6 +10,8 @@ import (
"time" "time"
"github.com/kataras/iris/websocket" "github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
) )
const ( const (
@ -21,17 +23,17 @@ const (
// this can be shared with the server.go's. // this can be shared with the server.go's.
// `NSConn.Conn` has the `IsClient() bool` method which can be used to // `NSConn.Conn` has the `IsClient() bool` method which can be used to
// check if that's is a client or a server-side callback. // check if that's is a client or a server-side callback.
var clientEvents = websocket.Namespaces{ var clientEvents = neffos.Namespaces{
namespace: websocket.Events{ namespace: neffos.Events{
websocket.OnNamespaceConnected: func(c *websocket.NSConn, msg websocket.Message) error { neffos.OnNamespaceConnected: func(c *neffos.NSConn, msg neffos.Message) error {
log.Printf("connected to namespace: %s", msg.Namespace) log.Printf("connected to namespace: %s", msg.Namespace)
return nil return nil
}, },
websocket.OnNamespaceDisconnect: func(c *websocket.NSConn, msg websocket.Message) error { neffos.OnNamespaceDisconnect: func(c *neffos.NSConn, msg neffos.Message) error {
log.Printf("disconnected from namespace: %s", msg.Namespace) log.Printf("disconnected from namespace: %s", msg.Namespace)
return nil return nil
}, },
"chat": func(c *websocket.NSConn, msg websocket.Message) error { "chat": func(c *neffos.NSConn, msg neffos.Message) error {
log.Printf("%s", string(msg.Body)) log.Printf("%s", string(msg.Body))
return nil return nil
}, },
@ -42,7 +44,7 @@ func main() {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(dialAndConnectTimeout)) ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(dialAndConnectTimeout))
defer cancel() defer cancel()
client, err := websocket.Dial(ctx, websocket.DefaultGorillaDialer, endpoint, clientEvents) client, err := neffos.Dial(ctx, websocket.DefaultGorillaDialer, endpoint, clientEvents)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -5,26 +5,29 @@ import (
"github.com/kataras/iris" "github.com/kataras/iris"
"github.com/kataras/iris/websocket" "github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
) )
const namespace = "default" const namespace = "default"
// if namespace is empty then simply websocket.Events{...} can be used instead. // if namespace is empty then simply neffos.Events{...} can be used instead.
var serverEvents = websocket.Namespaces{ var serverEvents = neffos.Namespaces{
namespace: websocket.Events{ namespace: neffos.Events{
websocket.OnNamespaceConnected: func(nsConn *websocket.NSConn, msg websocket.Message) error { neffos.OnNamespaceConnected: func(nsConn *neffos.NSConn, msg neffos.Message) error {
// with `websocket.GetContext` you can retrieve the Iris' `Context`.
ctx := websocket.GetContext(nsConn.Conn)
log.Printf("[%s] connected to namespace [%s] with IP [%s]", log.Printf("[%s] connected to namespace [%s] with IP [%s]",
nsConn, msg.Namespace, nsConn, msg.Namespace,
// with `GetContext` you can retrieve the Iris' `Context`, alternatively ctx.RemoteAddr())
// you can use the `nsConn.Conn.Socket().Request()` to get the raw `*http.Request`.
websocket.GetContext(nsConn.Conn).RemoteAddr())
return nil return nil
}, },
websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error { neffos.OnNamespaceDisconnect: func(nsConn *neffos.NSConn, msg neffos.Message) error {
log.Printf("[%s] disconnected from namespace [%s]", nsConn, msg.Namespace) log.Printf("[%s] disconnected from namespace [%s]", nsConn, msg.Namespace)
return nil return nil
}, },
"chat": func(nsConn *websocket.NSConn, msg websocket.Message) error { "chat": func(nsConn *neffos.NSConn, msg neffos.Message) error {
// room.String() returns -> NSConn.String() returns -> Conn.String() returns -> Conn.ID() // room.String() returns -> NSConn.String() returns -> Conn.String() returns -> Conn.ID()
log.Printf("[%s] sent: %s", nsConn, string(msg.Body)) log.Printf("[%s] sent: %s", nsConn, string(msg.Body))
@ -39,7 +42,7 @@ var serverEvents = websocket.Namespaces{
func main() { func main() {
app := iris.New() app := iris.New()
websocketServer := websocket.New( websocketServer := neffos.New(
websocket.DefaultGorillaUpgrader, /* DefaultGobwasUpgrader can be used too. */ websocket.DefaultGorillaUpgrader, /* DefaultGobwasUpgrader can be used too. */
serverEvents) serverEvents)

View File

@ -4,8 +4,9 @@ import (
"log" "log"
"github.com/kataras/iris" "github.com/kataras/iris"
"github.com/kataras/iris/websocket" "github.com/kataras/iris/websocket"
"github.com/kataras/neffos"
) )
type clientPage struct { type clientPage struct {
@ -25,8 +26,8 @@ func main() {
// and contains only one registered event which is the `OnNativeMessage`. // and contains only one registered event which is the `OnNativeMessage`.
// When `Events{...}` is used instead of `Namespaces{ "namespaceName": Events{...}}` // When `Events{...}` is used instead of `Namespaces{ "namespaceName": Events{...}}`
// then the namespace is empty "". // then the namespace is empty "".
ws := websocket.New(websocket.DefaultGorillaUpgrader, websocket.Events{ ws := neffos.New(websocket.DefaultGorillaUpgrader, neffos.Events{
websocket.OnNativeMessage: func(nsConn *websocket.NSConn, msg websocket.Message) error { neffos.OnNativeMessage: func(nsConn *neffos.NSConn, msg neffos.Message) error {
log.Printf("Server got: %s from [%s]", msg.Body, nsConn.Conn.ID()) log.Printf("Server got: %s from [%s]", msg.Body, nsConn.Conn.ID())
nsConn.Conn.Server().Broadcast(nsConn, msg) nsConn.Conn.Server().Broadcast(nsConn, msg)
@ -34,12 +35,12 @@ func main() {
}, },
}) })
ws.OnConnect = func(c *websocket.Conn) error { ws.OnConnect = func(c *neffos.Conn) error {
log.Printf("[%s] Connected to server!", c.ID()) log.Printf("[%s] Connected to server!", c.ID())
return nil return nil
} }
ws.OnDisconnect = func(c *websocket.Conn) { ws.OnDisconnect = func(c *neffos.Conn) {
log.Printf("[%s] Disconnected from server", c.ID()) log.Printf("[%s] Disconnected from server", c.ID())
} }

View File

@ -0,0 +1,6 @@
# Secure Websockets
1. Run your server through `https://` (`iris.Run(iris.TLS)` or `iris.Run(iris.AutoTLS)` or a custom `iris.Listener(...)`)
2. Nothing changes inside the whole app, including the websocket side
3. The clients must dial the websocket server endpoint (i.e `/echo`) via `wss://` prefix (instead of the non-secure `ws://`), for example `wss://example.com/echo`
4. Ready to GO.

View File

@ -1,174 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"time"
"github.com/kataras/iris"
"github.com/kataras/iris/websocket"
)
type clientPage struct {
Title string
Host string
}
func main() {
app := iris.New()
app.RegisterView(iris.HTML("./templates", ".html")) // select the html engine to serve templates
ws := websocket.New(websocket.Config{})
// register the server on an endpoint.
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
app.Get("/my_endpoint", ws.Handler())
// serve the javascript builtin client-side library,
// see websockets.html script tags, this path is used.
app.Any("/iris-ws.js", func(ctx iris.Context) {
ctx.Write(websocket.ClientSource)
})
app.HandleDir("/js", "./static/js")
app.Get("/", func(ctx iris.Context) {
// send our custom javascript source file before client really asks for that
// using the go v1.8's HTTP/2 Push.
// Note that you have to listen using ListenTLS in order this to work.
if err := ctx.ResponseWriter().Push("/js/chat.js", nil); err != nil {
ctx.Application().Logger().Warn(err.Error())
}
ctx.ViewData("", clientPage{"Client Page", ctx.Host()})
ctx.View("client.html")
})
var myChatRoom = "room1"
ws.OnConnection(func(c websocket.Connection) {
// Context returns the (upgraded) iris.Context of this connection
// avoid using it, you normally don't need it,
// websocket has everything you need to authenticate the user BUT if it's necessary
// then you use it to receive user information, for example: from headers.
// ctx := c.Context()
// join to a room (optional)
c.Join(myChatRoom)
c.On("chat", func(message string) {
if message == "leave" {
c.Leave(myChatRoom)
c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.")
c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.")
return
}
// to all except this connection ->
// c.To(websocket.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message)
// to all connected clients: c.To(websocket.All)
// to the client itself ->
//c.Emit("chat", "Message from myself: "+message)
//send the message to the whole room,
//all connections are inside this room will receive this message
c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message)
})
// or create a new leave event
// c.On("leave", func() {
// c.Leave(myChatRoom)
// })
c.OnDisconnect(func() {
fmt.Printf("Connection with ID: %s has been disconnected!\n", c.ID())
})
})
listenTLS(app)
}
// a test listenTLS for our localhost
func listenTLS(app *iris.Application) {
const (
testTLSCert = `-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIJAOYzROngkH6NMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
BAMMDmxvY2FsaG9zdDo4MDgwMB4XDTE3MDIxNzAzNDM1NFoXDTI3MDIxNTAzNDM1
NFowGTEXMBUGA1UEAwwObG9jYWxob3N0OjgwODAwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCfsiVHO14FpKsi0pvBv68oApQm2MO+dCvq87sDU4E0QJhG
KV1RCUmQVypChEqdLlUQsopcXSyKwbWoyg1/KNHYO3DHMfePb4bC1UD2HENq7Ph2
8QJTEi/CJvUB9hqke/YCoWYdjFiI3h3Hw8q5whGO5XR3R23z69vr5XxoNlcF2R+O
TdkzArd0CWTZS27vbgdnyi9v3Waydh/rl+QRtPUgEoCEqOOkMSMldXO6Z9GlUk9b
FQHwIuEnlSoVFB5ot5cqebEjJnWMLLP83KOCQekJeHZOyjeTe8W0Fy1DGu5fvFNh
xde9e/7XlFE//00vT7nBmJAUV/2CXC8U5lsjLEqdAgMBAAGjUDBOMB0GA1UdDgQW
BBQOfENuLn/t0Z4ZY1+RPWaz7RBH+TAfBgNVHSMEGDAWgBQOfENuLn/t0Z4ZY1+R
PWaz7RBH+TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBG7AEEuIq6
rWCE5I2t4IXz0jN7MilqEhUWDbUajl1paYf6Ikx5QhMsFx21p6WEWYIYcnWAKZe2
chAgnnGojuxdx0qjiaH4N4xWGHsWhaesnIF1xJepLlX3kJZQURvRxM4wlljlQPIb
9tqzKP131K1HDqplAtp7nWQ72m3J0ZfzH0mYIUxuaS/uQIVtgKqdilwy/VE5dRZ9
QFIb4G9TnNThXMqgTLjfNr33jVbTuv6fzKHYNbCkP3L10ydEs/ddlREmtsn9nE8Q
XCTIYXzA2kr5kWk7d3LkUiSvu3g2S1Ol1YaIKaOQyRveseCGwR4xohLT+dPUW9dL
3hDVLlwE3mB3
-----END CERTIFICATE-----
`
testTLSKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAn7IlRzteBaSrItKbwb+vKAKUJtjDvnQr6vO7A1OBNECYRild
UQlJkFcqQoRKnS5VELKKXF0sisG1qMoNfyjR2DtwxzH3j2+GwtVA9hxDauz4dvEC
UxIvwib1AfYapHv2AqFmHYxYiN4dx8PKucIRjuV0d0dt8+vb6+V8aDZXBdkfjk3Z
MwK3dAlk2Utu724HZ8ovb91msnYf65fkEbT1IBKAhKjjpDEjJXVzumfRpVJPWxUB
8CLhJ5UqFRQeaLeXKnmxIyZ1jCyz/NyjgkHpCXh2Tso3k3vFtBctQxruX7xTYcXX
vXv+15RRP/9NL0+5wZiQFFf9glwvFOZbIyxKnQIDAQABAoIBAEzBx4ExW8PCni8i
o5LAm2PTuXniflMwa1uGwsCahmOjGI3AnAWzPRSPkNRf2a0q8+AOsMosTphy+umi
FFKmQBZ6m35i2earaE6FSbABbbYbKGGi/ccH2sSrDOBgdfXRTzF8eiSBrJw8hnvZ
87rNOLtCNnSOdJ7lItODfgRo+fLo4uQenJ8VONYwtwm1ejn8qLXq8O5zF66IYUD6
gAzqOiAWumgZL0tEmndeQ+noe4STpJZlOjiCsA12NiJaKDDeDIn5A/pXce+bYNfJ
k4yoroyq/JXBkhyuZDvX9vYp5AA+Q68h8/KmsKkifUgSGSHun5/80lYyT/f60TLX
PxT9GYECgYEA0s8qck7L29nBBTQ6IPF3GHGmqiRdfH+qhP/Jn4NtoW3XuVe4A15i
REq1L8WAiOUIBnBaD8HzbeioqJJYx1pu7x9h/GCNDhdBfwhTjnBe+JjfLqvJKnc0
HUT5wj4DVqattxKzUW8kTRBSWtVremzeffDo+EL6dnR7Bc02Ibs4WpUCgYEAwe34
Uqhie+/EFr4HjYRUNZSNgYNAJkKHVxk4qGzG5VhvjPafnHUbo+Kk/0QW7eIB+kvR
FDO8oKh9wTBrWZEcLJP4jDIKh4y8hZTo9B8EjxFONXVxZlOSYuGjheL8AiLzE7L9
C1spaKMM/MyxAXDRHpG/NeEgXM7Kn6kUGwJdNekCgYAshLNiEGHcu8+XWcAs1NFh
yB56L9PORuerzpi1pvuv65JzAaNKktQNt/krbXoHbtaTBYb/bOYLf+aeMsmsz9w9
g1MeCQXAxAiA2zFKE1D7Ds2S/ZQt8559z+MusgnicrCcyMY1nFL+M0QxCoD4CaWy
0v1f8EUUXuTcBMo5tV/hQQKBgDoBBW8jsiFDu7DZscSgOde00QZVzZAkAfsJLisi
LfNXGjZdZawUUuoX1iYLpZgNK25D0wtp1hdvjf2Ej/dAMd8bexHjvcaBT7ncqjiq
NmDcWjofIIXspTIyLwjStXGmJnJT7N/CqoYDjtTmHGND7Shpi3mAFn/r0isjFUJm
2J5RAoGALuGXxzmSRWmkIp11F/Qr3PBFWBWkrRWaH2TRLMhrU/wO8kCsSyo4PmAZ
ltOfD7InpDiCu43hcDPQ/29FUbDnmAhvMnmIQuHXGgPF/LhqEhbKPA/o/eZdQVCK
QG+tmveBBIYMed5YbWstZu/95lIHF+u8Hl+Z6xgveozfE5yqiUA=
-----END RSA PRIVATE KEY-----
`
)
// create the key and cert files on the fly, and delete them when this test finished
certFile, ferr := ioutil.TempFile("", "cert")
if ferr != nil {
panic(ferr)
}
keyFile, ferr := ioutil.TempFile("", "key")
if ferr != nil {
panic(ferr)
}
certFile.WriteString(testTLSCert)
keyFile.WriteString(testTLSKey)
// https://localhost
app.Run(iris.TLS("localhost:443", certFile.Name(), keyFile.Name()))
certFile.Close()
time.Sleep(50 * time.Millisecond)
os.Remove(certFile.Name())
keyFile.Close()
time.Sleep(50 * time.Millisecond)
os.Remove(keyFile.Name())
}

View File

@ -1,38 +0,0 @@
var messageTxt;
var messages;
$(function () {
messageTxt = $("#messageTxt");
messages = $("#messages");
/* secure wss because we ListenTLS */
w = new Ws("wss://" + HOST + "/my_endpoint");
w.OnConnect(function () {
console.log("Websocket connection established");
});
w.OnDisconnect(function () {
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
});
w.On("chat", function (message) {
appendMessage($("<div>" + message + "</div>"));
});
$("#sendBtn").click(function () {
w.Emit("chat", messageTxt.val().toString());
messageTxt.val("");
});
})
function appendMessage(messageDiv) {
var theDiv = messages[0];
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
messageDiv.appendTo(messages);
if (doScroll) {
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
}
}

View File

@ -1,24 +0,0 @@
<html>
<head>
<title>{{ .Title}}</title>
</head>
<body>
<div id="messages"
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
</div>
<input type="text" id="messageTxt" />
<button type="button" id="sendBtn">Send</button>
<script type="text/javascript">
var HOST = {{.Host}}
</script>
<script src="/js/vendor/jquery-2.2.3.min.js"></script>
<!-- This is auto-serving by the iris, you don't need to have this file in your disk-->
<script src="/iris-ws.js"></script>
<!-- -->
<script src="/js/chat.js"></script>
</body>
</html>

View File

@ -1,44 +0,0 @@
package main
import (
"github.com/kataras/iris"
"github.com/googollee/go-socket.io"
)
/*
go get -u github.com/googollee/go-socket.io
*/
func main() {
app := iris.New()
server, err := socketio.NewServer(nil)
if err != nil {
app.Logger().Fatal(err)
}
server.On("connection", func(so socketio.Socket) {
app.Logger().Infof("on connection")
so.Join("chat")
so.On("chat message", func(msg string) {
app.Logger().Infof("emit: %v", so.Emit("chat message", msg))
so.BroadcastTo("chat", "chat message", msg)
})
so.On("disconnection", func() {
app.Logger().Infof("on disconnect")
})
})
server.On("error", func(so socketio.Socket, err error) {
app.Logger().Errorf("error: %v", err)
})
// serve the socket.io endpoint.
app.Any("/socket.io/{p:path}", iris.FromStd(server))
// serve the index.html and the javascript libraries at
// http://localhost:8080
app.HandleDir("/", "./public")
app.Run(iris.Addr("localhost:8080"), iris.WithoutPathCorrection)
}

View File

@ -1,38 +0,0 @@
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }
form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; }
#messages li:nth-child(odd) { background: #eee; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io-1.3.7.js"></script>
<script src="/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message with ack', $('#m').val(), function(data){
$('#messages').append($('<li>').text('ACK CALLBACK: ' + data));
});
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long