forked from mirror/websocket
Add IsUnexpectedCloseError
This commit is contained in:
parent
a2d85bcbfc
commit
615f23bc98
20
conn.go
20
conn.go
|
@ -115,6 +115,20 @@ func IsCloseError(err error, codes ...int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsUnexpectedCloseError returns boolean indicating whether the error is a
|
||||||
|
// *CloseError with a code not in the list of expected codes.
|
||||||
|
func IsUnexpectedCloseError(err error, expectedCodes ...int) bool {
|
||||||
|
if e, ok := err.(*CloseError); ok {
|
||||||
|
for _, code := range expectedCodes {
|
||||||
|
if e.Code == code {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errWriteTimeout = &netError{msg: "websocket: write timeout", timeout: true, temporary: true}
|
errWriteTimeout = &netError{msg: "websocket: write timeout", timeout: true, temporary: true}
|
||||||
errUnexpectedEOF = &CloseError{Code: CloseAbnormalClosure, Text: io.ErrUnexpectedEOF.Error()}
|
errUnexpectedEOF = &CloseError{Code: CloseAbnormalClosure, Text: io.ErrUnexpectedEOF.Error()}
|
||||||
|
@ -321,9 +335,6 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
|
||||||
//
|
//
|
||||||
// There can be at most one open writer on a connection. NextWriter closes the
|
// There can be at most one open writer on a connection. NextWriter closes the
|
||||||
// previous writer if the application has not already done so.
|
// previous writer if the application has not already done so.
|
||||||
//
|
|
||||||
// The NextWriter method and the writers returned from the method cannot be
|
|
||||||
// accessed by more than one goroutine at a time.
|
|
||||||
func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
|
func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) {
|
||||||
if c.writeErr != nil {
|
if c.writeErr != nil {
|
||||||
return nil, c.writeErr
|
return nil, c.writeErr
|
||||||
|
@ -708,7 +719,8 @@ func (c *Conn) handleProtocolError(message string) error {
|
||||||
// the previous message if the application has not already consumed it.
|
// the previous message if the application has not already consumed it.
|
||||||
//
|
//
|
||||||
// Errors returned from NextReader are permanent. If NextReader returns a
|
// Errors returned from NextReader are permanent. If NextReader returns a
|
||||||
// non-nil error, then all subsequent calls to NextReader will the same error.
|
// non-nil error, then all subsequent calls to NextReader return the same
|
||||||
|
// error.
|
||||||
func (c *Conn) NextReader() (messageType int, r io.Reader, err error) {
|
func (c *Conn) NextReader() (messageType int, r io.Reader, err error) {
|
||||||
|
|
||||||
c.readSeq++
|
c.readSeq++
|
||||||
|
|
20
conn_test.go
20
conn_test.go
|
@ -291,3 +291,23 @@ func TestCloseError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unexpectedCloseErrorTests = []struct {
|
||||||
|
err error
|
||||||
|
codes []int
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{&CloseError{Code: CloseNormalClosure}, []int{CloseNormalClosure}, false},
|
||||||
|
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived}, true},
|
||||||
|
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived, CloseNormalClosure}, false},
|
||||||
|
{errors.New("hello"), []int{CloseNormalClosure}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnexpectedCloseErrors(t *testing.T) {
|
||||||
|
for _, tt := range unexpectedCloseErrorTests {
|
||||||
|
ok := IsUnexpectedCloseError(tt.err, tt.codes...)
|
||||||
|
if ok != tt.ok {
|
||||||
|
t.Errorf("IsUnexpectedCloseError(%#v, %#v) returned %v, want %v", tt.err, tt.codes, ok, tt.ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package websocket_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The websocket.IsUnexpectedCloseError function is useful for identifying
|
||||||
|
// application and protocol errors.
|
||||||
|
//
|
||||||
|
// This server application works with a client application running in the
|
||||||
|
// browser. The client application does not explicitly close the websocket. The
|
||||||
|
// only expected close message from the client has the code
|
||||||
|
// websocket.CloseGoingAway. All other other close messages are likely the
|
||||||
|
// result of an application or protocol error and are logged to aid debugging.
|
||||||
|
func ExampleIsUnexpectedCloseError(err error, c *websocket.Conn, req *http.Request) {
|
||||||
|
for {
|
||||||
|
messageType, p, err := c.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
||||||
|
log.Println("error: %v, user-agent: %v", err, req.Header.Get("User-Agent"))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
processMesage(messageType, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processMesage(mt int, p []byte) {}
|
||||||
|
|
||||||
|
// TestX prevents godoc from showing this entire file in the example. Remove
|
||||||
|
// this function when a second example is added.
|
||||||
|
func TestX(t *testing.T) {}
|
Loading…
Reference in New Issue