From b307b475131604cad9f43f1f30cc757725eca80e Mon Sep 17 00:00:00 2001
From: Anmol Sethi <hi@nhooyr.io>
Date: Mon, 13 Apr 2020 21:22:14 -0400
Subject: [PATCH] Improve docs and fix examples

Closes #207
---
 README.md                                     |  17 +--
 ci/test.mk                                    |   2 +-
 example_test.go                               | 120 +++++++++---------
 examples/README.md                            |   4 +
 {chat-example => examples/chat}/README.md     |   0
 {chat-example => examples/chat}/chat.go       |   0
 {chat-example => examples/chat}/chat_test.go  |   0
 {chat-example => examples/chat}/go.sum        |   0
 {chat-example => examples/chat}/index.css     |   0
 {chat-example => examples/chat}/index.html    |   0
 {chat-example => examples/chat}/index.js      |   0
 {chat-example => examples/chat}/main.go       |   0
 example_echo_test.go => examples/echo/echo.go |   4 +-
 13 files changed, 78 insertions(+), 69 deletions(-)
 create mode 100644 examples/README.md
 rename {chat-example => examples/chat}/README.md (100%)
 rename {chat-example => examples/chat}/chat.go (100%)
 rename {chat-example => examples/chat}/chat_test.go (100%)
 rename {chat-example => examples/chat}/go.sum (100%)
 rename {chat-example => examples/chat}/index.css (100%)
 rename {chat-example => examples/chat}/index.html (100%)
 rename {chat-example => examples/chat}/index.js (100%)
 rename {chat-example => examples/chat}/main.go (100%)
 rename example_echo_test.go => examples/echo/echo.go (99%)

diff --git a/README.md b/README.md
index 2d71ce0..3debf2f 100644
--- a/README.md
+++ b/README.md
@@ -15,9 +15,9 @@ go get nhooyr.io/websocket
 - Minimal and idiomatic API
 - First class [context.Context](https://blog.golang.org/context) support
 - Fully passes the WebSocket [autobahn-testsuite](https://github.com/crossbario/autobahn-testsuite)
-- Thorough unit tests with [90% coverage](https://coveralls.io/github/nhooyr/websocket)
-- [Minimal dependencies](https://pkg.go.dev/nhooyr.io/websocket?tab=imports)
-- JSON and protobuf helpers in the [wsjson](https://pkg.go.dev/nhooyr.io/websocket/wsjson?tab=doc) and [wspb](https://pkg.go.dev/nhooyr.io/websocket/wspb?tab=doc) subpackages
+- Thorough tests with [90% coverage](https://coveralls.io/github/nhooyr/websocket)
+- [Zero dependencies](https://pkg.go.dev/nhooyr.io/websocket?tab=imports)
+- JSON and protobuf helpers in the [wsjson](https://pkg.go.dev/nhooyr.io/websocket/wsjson) and [wspb](https://pkg.go.dev/nhooyr.io/websocket/wspb) subpackages
 - Zero alloc reads and writes
 - Concurrent writes
 - [Close handshake](https://godoc.org/nhooyr.io/websocket#Conn.Close)
@@ -32,9 +32,10 @@ go get nhooyr.io/websocket
 
 ## Examples
 
-For a production quality example that demonstrates the complete API, see the [echo example](https://godoc.org/nhooyr.io/websocket#example-package--Echo).
+For a production quality example that demonstrates the complete API, see the
+[echo example](./examples/echo).
 
-For a full stack example, see [./chat-example](./chat-example).
+For a full stack example, see the [chat example](./examples/chat).
 
 ### Server
 
@@ -98,7 +99,7 @@ Advantages of nhooyr.io/websocket:
 - [net.Conn](https://godoc.org/nhooyr.io/websocket#NetConn) wrapper
 - Zero alloc reads and writes ([gorilla/websocket#535](https://github.com/gorilla/websocket/issues/535))
 - Full [context.Context](https://blog.golang.org/context) support
-- Dials use [net/http.Client](https://golang.org/pkg/net/http/#Client)
+- Dial uses [net/http.Client](https://golang.org/pkg/net/http/#Client)
   - Will enable easy HTTP/2 support in the future
   - Gorilla writes directly to a net.Conn and so duplicates features of net/http.Client.
 - Concurrent writes
@@ -111,7 +112,7 @@ Advantages of nhooyr.io/websocket:
   - Gorilla's implementation is slower and uses [unsafe](https://golang.org/pkg/unsafe/).
 - Full [permessage-deflate](https://tools.ietf.org/html/rfc7692) compression extension support
   - Gorilla only supports no context takeover mode
-  - We use [klauspost/compress](https://github.com/klauspost/compress) for much lower memory usage ([gorilla/websocket#203](https://github.com/gorilla/websocket/issues/203))
+  - We use a vendored [klauspost/compress](https://github.com/klauspost/compress) for much lower memory usage ([gorilla/websocket#203](https://github.com/gorilla/websocket/issues/203))
 - [CloseRead](https://godoc.org/nhooyr.io/websocket#Conn.CloseRead) helper ([gorilla/websocket#492](https://github.com/gorilla/websocket/issues/492))
 - Actively maintained ([gorilla/websocket#370](https://github.com/gorilla/websocket/issues/370))
 
@@ -120,7 +121,7 @@ Advantages of nhooyr.io/websocket:
 [golang.org/x/net/websocket](https://godoc.org/golang.org/x/net/websocket) is deprecated.
 See [golang/go/issues/18152](https://github.com/golang/go/issues/18152).
 
-The [net.Conn](https://godoc.org/nhooyr.io/websocket#NetConn) wrapper will ease in transitioning
+The [net.Conn](https://godoc.org/nhooyr.io/websocket#NetConn) can help in transitioning
 to nhooyr.io/websocket.
 
 #### gobwas/ws
diff --git a/ci/test.mk b/ci/test.mk
index 291d6be..b2f92b7 100644
--- a/ci/test.mk
+++ b/ci/test.mk
@@ -14,4 +14,4 @@ gotest:
 	go test -timeout=30m -covermode=atomic -coverprofile=ci/out/coverage.prof -coverpkg=./... $${GOTESTFLAGS-} ./...
 	sed -i '/stringer\.go/d' ci/out/coverage.prof
 	sed -i '/nhooyr.io\/websocket\/internal\/test/d' ci/out/coverage.prof
-	sed -i '/chat-example/d' ci/out/coverage.prof
+	sed -i '/example/d' ci/out/coverage.prof
diff --git a/example_test.go b/example_test.go
index 39de0b8..632c4d6 100644
--- a/example_test.go
+++ b/example_test.go
@@ -4,17 +4,16 @@ import (
 	"context"
 	"log"
 	"net/http"
-	"os"
-	"os/signal"
 	"time"
 
 	"nhooyr.io/websocket"
 	"nhooyr.io/websocket/wsjson"
 )
 
-// This example accepts a WebSocket connection, reads a single JSON
-// message from the client and then closes the connection.
 func ExampleAccept() {
+	// This handler accepts a WebSocket connection, reads a single JSON
+	// message from the client and then closes the connection.
+
 	fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		c, err := websocket.Accept(w, r, nil)
 		if err != nil {
@@ -40,9 +39,10 @@ func ExampleAccept() {
 	log.Fatal(err)
 }
 
-// This example dials a server, writes a single JSON message and then
-// closes the connection.
 func ExampleDial() {
+	// Dials a server, writes a single JSON message and then
+	// closes the connection.
+
 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
 	defer cancel()
 
@@ -60,9 +60,10 @@ func ExampleDial() {
 	c.Close(websocket.StatusNormalClosure, "")
 }
 
-// This example dials a server and then expects to be disconnected with status code
-// websocket.StatusNormalClosure.
 func ExampleCloseStatus() {
+	// Dials a server and then expects to be disconnected with status code
+	// websocket.StatusNormalClosure.
+
 	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
 	defer cancel()
 
@@ -78,9 +79,9 @@ func ExampleCloseStatus() {
 	}
 }
 
-// This example shows how to correctly handle a WebSocket connection
-// on which you will only write and do not expect to read data messages.
 func Example_writeOnly() {
+	// This handler demonstrates how to correctly handle a write only WebSocket connection.
+	// i.e you only expect to write messages and do not expect to read any messages.
 	fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		c, err := websocket.Accept(w, r, nil)
 		if err != nil {
@@ -116,9 +117,9 @@ func Example_writeOnly() {
 	log.Fatal(err)
 }
 
-// This example demonstrates how to safely accept cross origin WebSockets
-// from the origin example.com.
 func Example_crossOrigin() {
+	// This handler demonstrates how to safely accept cross origin WebSockets
+	// from the origin example.com.
 	fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
 			OriginPatterns: []string{"example.com"},
@@ -141,52 +142,57 @@ func Example_crossOrigin() {
 // for 10 seconds.
 // If you CTRL+C while a connection is open, it will wait at most 30s
 // for all connections to terminate before shutting down.
-func ExampleGrace() {
-	fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		c, err := websocket.Accept(w, r, nil)
-		if err != nil {
-			log.Println(err)
-			return
-		}
-		defer c.Close(websocket.StatusInternalError, "the sky is falling")
-
-		ctx := c.CloseRead(r.Context())
-		select {
-		case <-ctx.Done():
-		case <-time.After(time.Second * 10):
-		}
-
-		c.Close(websocket.StatusNormalClosure, "")
-	})
-
-	var g websocket.Grace
-	s := &http.Server{
-		Handler:      g.Handler(fn),
-		ReadTimeout:  time.Second * 15,
-		WriteTimeout: time.Second * 15,
-	}
-
-	errc := make(chan error, 1)
-	go func() {
-		errc <- s.ListenAndServe()
-	}()
-
-	sigs := make(chan os.Signal, 1)
-	signal.Notify(sigs, os.Interrupt)
-	select {
-	case err := <-errc:
-		log.Printf("failed to listen and serve: %v", err)
-	case sig := <-sigs:
-		log.Printf("terminating: %v", sig)
-	}
-
-	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
-	defer cancel()
-	s.Shutdown(ctx)
-	g.Shutdown(ctx)
-}
+// func ExampleGrace() {
+// 	fn := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+// 		c, err := websocket.Accept(w, r, nil)
+// 		if err != nil {
+// 			log.Println(err)
+// 			return
+// 		}
+// 		defer c.Close(websocket.StatusInternalError, "the sky is falling")
+//
+// 		ctx := c.CloseRead(r.Context())
+// 		select {
+// 		case <-ctx.Done():
+// 		case <-time.After(time.Second * 10):
+// 		}
+//
+// 		c.Close(websocket.StatusNormalClosure, "")
+// 	})
+//
+// 	var g websocket.Grace
+// 	s := &http.Server{
+// 		Handler:      g.Handler(fn),
+// 		ReadTimeout:  time.Second * 15,
+// 		WriteTimeout: time.Second * 15,
+// 	}
+//
+// 	errc := make(chan error, 1)
+// 	go func() {
+// 		errc <- s.ListenAndServe()
+// 	}()
+//
+// 	sigs := make(chan os.Signal, 1)
+// 	signal.Notify(sigs, os.Interrupt)
+// 	select {
+// 	case err := <-errc:
+// 		log.Printf("failed to listen and serve: %v", err)
+// 	case sig := <-sigs:
+// 		log.Printf("terminating: %v", sig)
+// 	}
+//
+// 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
+// 	defer cancel()
+// 	s.Shutdown(ctx)
+// 	g.Shutdown(ctx)
+// }
 
 // This example demonstrates full stack chat with an automated test.
 func Example_fullStackChat() {
-	// https://github.com/nhooyr/websocket/tree/master/chat-example
+	// https://github.com/nhooyr/websocket/tree/master/examples/chat
+}
+
+// This example demonstrates a echo server.
+func Example_echo() {
+	// https://github.com/nhooyr/websocket/tree/master/examples/echo
 }
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..3cb437a
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,4 @@
+# Examples
+
+This directory contains more involved examples unsuitable
+for display with godoc.
diff --git a/chat-example/README.md b/examples/chat/README.md
similarity index 100%
rename from chat-example/README.md
rename to examples/chat/README.md
diff --git a/chat-example/chat.go b/examples/chat/chat.go
similarity index 100%
rename from chat-example/chat.go
rename to examples/chat/chat.go
diff --git a/chat-example/chat_test.go b/examples/chat/chat_test.go
similarity index 100%
rename from chat-example/chat_test.go
rename to examples/chat/chat_test.go
diff --git a/chat-example/go.sum b/examples/chat/go.sum
similarity index 100%
rename from chat-example/go.sum
rename to examples/chat/go.sum
diff --git a/chat-example/index.css b/examples/chat/index.css
similarity index 100%
rename from chat-example/index.css
rename to examples/chat/index.css
diff --git a/chat-example/index.html b/examples/chat/index.html
similarity index 100%
rename from chat-example/index.html
rename to examples/chat/index.html
diff --git a/chat-example/index.js b/examples/chat/index.js
similarity index 100%
rename from chat-example/index.js
rename to examples/chat/index.js
diff --git a/chat-example/main.go b/examples/chat/main.go
similarity index 100%
rename from chat-example/main.go
rename to examples/chat/main.go
diff --git a/example_echo_test.go b/examples/echo/echo.go
similarity index 99%
rename from example_echo_test.go
rename to examples/echo/echo.go
index fb212c1..0f31235 100644
--- a/example_echo_test.go
+++ b/examples/echo/echo.go
@@ -1,6 +1,4 @@
-// +build !js
-
-package websocket_test
+package main
 
 import (
 	"context"
-- 
GitLab