Skip to content

Separate internal and net.Conn implementations #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 13, 2017
41 changes: 25 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
websocket
=========

Package websocket provides high- and low-level bindings for the browser's WebSocket API.
Packages websocket and websocketjs provide high- and low-level bindings for the browser's WebSocket API (respectively).

The high-level bindings act like a regular net.Conn. They can be used as such. For example:
The high-level bindings offer a Dial function that returns a regular net.Conn.
It can be used similarly to net package.

```Go
c, err := websocket.Dial("ws://localhost/socket") // Blocks until connection is established
if err != nil { panic(err) }
conn, err := websocket.Dial("ws://localhost/socket") // Blocks until connection is established.
if err != nil {
// handle error
}

buf := make([]byte, 1024)
n, err = c.Read(buf) // Blocks until a WebSocket frame is received
if err != nil { panic(err) }
n, err = conn.Read(buf) // Blocks until a WebSocket frame is received.
doSomethingWithData(buf[:n])
if err != nil {
// handle error
}

_, err = c.Write([]byte("Hello!"))
if err != nil { panic(err) }
_, err = conn.Write([]byte("Hello!"))
// ...

err = c.Close()
if err != nil { panic(err) }
err = conn.Close()
// ...
```

The low-level bindings use the typical JavaScript idioms.
The low-level bindings work with typical JavaScript idioms, such as adding event listeners with callbacks.

```Go
ws, err := websocket.New("ws://localhost/socket") // Does not block.
if err != nil { panic(err) }
ws, err := websocketjs.New("ws://localhost/socket") // Does not block.
if err != nil {
// handle error
}

onOpen := func(ev *js.Object) {
err := ws.Send([]byte("Hello!")) // Send as a binary frame
err := ws.Send("Hello!") // Send a text frame
err := ws.Send([]byte("Hello!")) // Send a binary frame.
// ...
err := ws.Send("Hello!") // Send a text frame.
// ...
}

ws.AddEventListener("open", false, onOpen)
Expand All @@ -38,5 +47,5 @@ ws.AddEventListener("close", false, onClose)
ws.AddEventListener("error", false, onError)

err = ws.Close()
if err != nil { panic(err) }
// ...
```
5 changes: 3 additions & 2 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/gopherjs/gopherjs/js"
"github.com/gopherjs/websocket/websocketjs"
)

func beginHandlerOpen(ch chan error, removeHandlers func()) func(ev *js.Object) {
Expand Down Expand Up @@ -64,7 +65,7 @@ var errDeadlineReached = &deadlineErr{}
// Dial opens a new WebSocket connection. It will block until the connection is
// established or fails to connect.
func Dial(url string) (net.Conn, error) {
ws, err := New(url)
ws, err := websocketjs.New(url)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -107,7 +108,7 @@ func Dial(url string) (net.Conn, error) {

// conn is a high-level wrapper around WebSocket. It implements net.Conn interface.
type conn struct {
*WebSocket
*websocketjs.WebSocket

ch chan *messageEvent
readBuf *bytes.Reader
Expand Down
41 changes: 14 additions & 27 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,27 @@
// in the LICENSE file.

/*
Package websocket provides high- and low-level bindings for the browser's WebSocket API.
Package websocket provides high-level bindings for the browser's WebSocket API.

The high-level bindings act like a regular net.Conn. They can be used as such. For example:
These bindings offer a Dial function that returns a regular net.Conn.
It can be used similarly to net package.

c, err := websocket.Dial("ws://localhost/socket") // Blocks until connection is established
if err != nil { panic(err) }
conn, err := websocket.Dial("ws://localhost/socket") // Blocks until connection is established.
if err != nil {
// handle error
}

buf := make([]byte, 1024)
n, err = c.Read(buf) // Blocks until a WebSocket frame is received
if err != nil { panic(err) }
n, err = conn.Read(buf) // Blocks until a WebSocket frame is received.
doSomethingWithData(buf[:n])

_, err = c.Write([]byte("Hello!"))
if err != nil { panic(err) }

err = c.Close()
if err != nil { panic(err) }

The low-level bindings use the typical JavaScript idioms.

ws, err := websocket.New("ws://localhost/socket") // Does not block.
if err != nil { panic(err) }

onOpen := func(ev *js.Object) {
err := ws.Send([]byte("Hello!")) // Send as a binary frame
err := ws.Send("Hello!") // Send a text frame
if err != nil {
// handle error
}

ws.AddEventListener("open", false, onOpen)
ws.AddEventListener("message", false, onMessage)
ws.AddEventListener("close", false, onClose)
ws.AddEventListener("error", false, onError)
_, err = conn.Write([]byte("Hello!"))
// ...

err = ws.Close()
if err != nil { panic(err) }
err = conn.Close()
// ...
*/
package websocket
7 changes: 4 additions & 3 deletions test/test/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/gopherjs/gopherjs/js"
"github.com/gopherjs/websocket"
"github.com/gopherjs/websocket/websocketjs"
"github.com/rusco/qunit"
)

Expand All @@ -28,11 +29,11 @@ func getWSBaseURL() string {
func main() {
wsBaseURL := getWSBaseURL()

qunit.Module("websocket.WebSocket")
qunit.Module("websocketjs.WebSocket")
qunit.Test("Invalid URL", func(assert qunit.QUnitAssert) {
qunit.Expect(1)

ws, err := websocket.New("blah://blah.example/invalid")
ws, err := websocketjs.New("blah://blah.example/invalid")
if err == nil {
ws.Close()
assert.Ok(false, "Got no error, but expected an invalid URL error")
Expand All @@ -44,7 +45,7 @@ func main() {
qunit.AsyncTest("Immediate close", func() interface{} {
qunit.Expect(2)

ws, err := websocket.New(wsBaseURL + "immediate-close")
ws, err := websocketjs.New(wsBaseURL + "immediate-close")
if err != nil {
qunit.Ok(false, fmt.Sprintf("Error opening WebSocket: %s", err))
qunit.Start()
Expand Down
34 changes: 28 additions & 6 deletions wrapper.go → websocketjs/websocketjs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,35 @@
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.

package websocket
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be something like this:

/*
Package websocketjs provides low-level bindings for the browser's WebSocket API.

These bindings allow for using typical JavaScript idioms,
such as adding event listeners with callbacks. For example:

	ws, err := websocketjs.New("ws://localhost/socket") // Does not block.
	if err != nil { ... }
 
	onOpen := func(ev *js.Object) {
		err := ws.Send([]byte("Hello!")) // Send a binary frame.
		err := ws.Send("Hello!")         // Send a text frame.
	}

	ws.AddEventListener("open", false, onOpen)
	ws.AddEventListener("message", false, onMessage)
	ws.AddEventListener("close", false, onClose)
	ws.AddEventListener("error", false, onError)
 
	err = ws.Close()
	if err != nil { ... }
*/
package websocketjs

I've also replaced if err != nil { panic(err) } with if err != nil { ... }. I think it's clear enough that it means you should handle errors, and it's better not to show panic(err) as a way of doing that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 4293b3c

Package websocketjs provides low-level bindings for the browser's WebSocket API.

import (
"github.com/gopherjs/gopherjs/js"
)
These bindings work with typical JavaScript idioms,
such as adding event listeners with callbacks.

ws, err := websocketjs.New("ws://localhost/socket") // Does not block.
if err != nil {
// handle error
}

onOpen := func(ev *js.Object) {
err := ws.Send([]byte("Hello!")) // Send a binary frame.
// ...
err := ws.Send("Hello!") // Send a text frame.
// ...
}

ws.AddEventListener("open", false, onOpen)
ws.AddEventListener("message", false, onMessage)
ws.AddEventListener("close", false, onClose)
ws.AddEventListener("error", false, onError)

err = ws.Close()
// ...
*/
package websocketjs

import "github.com/gopherjs/gopherjs/js"

// ReadyState represents the state that a WebSocket is in. For more information
// about the available states, see
Expand Down Expand Up @@ -69,8 +93,6 @@ func New(url string) (ws *WebSocket, err error) {
// WebSocket is a low-level convenience wrapper around the browser's WebSocket
// object. For more information, see
// http://dev.w3.org/html5/websockets/#the-websocket-interface
//
// For the high-level wrapper, see Conn.
type WebSocket struct {
*js.Object

Expand Down