Moving to glide
Этот коммит содержится в:
161
vendor/github.com/gorilla/context/context_test.go
сгенерированный
поставляемый
Обычный файл
161
vendor/github.com/gorilla/context/context_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,161 @@
|
||||
// Copyright 2012 The Gorilla 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 context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type keyType int
|
||||
|
||||
const (
|
||||
key1 keyType = iota
|
||||
key2
|
||||
)
|
||||
|
||||
func TestContext(t *testing.T) {
|
||||
assertEqual := func(val interface{}, exp interface{}) {
|
||||
if val != exp {
|
||||
t.Errorf("Expected %v, got %v.", exp, val)
|
||||
}
|
||||
}
|
||||
|
||||
r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
|
||||
// Get()
|
||||
assertEqual(Get(r, key1), nil)
|
||||
|
||||
// Set()
|
||||
Set(r, key1, "1")
|
||||
assertEqual(Get(r, key1), "1")
|
||||
assertEqual(len(data[r]), 1)
|
||||
|
||||
Set(r, key2, "2")
|
||||
assertEqual(Get(r, key2), "2")
|
||||
assertEqual(len(data[r]), 2)
|
||||
|
||||
//GetOk
|
||||
value, ok := GetOk(r, key1)
|
||||
assertEqual(value, "1")
|
||||
assertEqual(ok, true)
|
||||
|
||||
value, ok = GetOk(r, "not exists")
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, false)
|
||||
|
||||
Set(r, "nil value", nil)
|
||||
value, ok = GetOk(r, "nil value")
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, true)
|
||||
|
||||
// GetAll()
|
||||
values := GetAll(r)
|
||||
assertEqual(len(values), 3)
|
||||
|
||||
// GetAll() for empty request
|
||||
values = GetAll(emptyR)
|
||||
if values != nil {
|
||||
t.Error("GetAll didn't return nil value for invalid request")
|
||||
}
|
||||
|
||||
// GetAllOk()
|
||||
values, ok = GetAllOk(r)
|
||||
assertEqual(len(values), 3)
|
||||
assertEqual(ok, true)
|
||||
|
||||
// GetAllOk() for empty request
|
||||
values, ok = GetAllOk(emptyR)
|
||||
assertEqual(value, nil)
|
||||
assertEqual(ok, false)
|
||||
|
||||
// Delete()
|
||||
Delete(r, key1)
|
||||
assertEqual(Get(r, key1), nil)
|
||||
assertEqual(len(data[r]), 2)
|
||||
|
||||
Delete(r, key2)
|
||||
assertEqual(Get(r, key2), nil)
|
||||
assertEqual(len(data[r]), 1)
|
||||
|
||||
// Clear()
|
||||
Clear(r)
|
||||
assertEqual(len(data), 0)
|
||||
}
|
||||
|
||||
func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) {
|
||||
<-wait
|
||||
for i := 0; i < iterations; i++ {
|
||||
Get(r, key)
|
||||
}
|
||||
done <- struct{}{}
|
||||
|
||||
}
|
||||
|
||||
func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) {
|
||||
<-wait
|
||||
for i := 0; i < iterations; i++ {
|
||||
Set(r, key, value)
|
||||
}
|
||||
done <- struct{}{}
|
||||
|
||||
}
|
||||
|
||||
func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) {
|
||||
|
||||
b.StopTimer()
|
||||
r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
done := make(chan struct{})
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
wait := make(chan struct{})
|
||||
|
||||
for i := 0; i < numReaders; i++ {
|
||||
go parallelReader(r, "test", iterations, wait, done)
|
||||
}
|
||||
|
||||
for i := 0; i < numWriters; i++ {
|
||||
go parallelWriter(r, "test", "123", iterations, wait, done)
|
||||
}
|
||||
|
||||
close(wait)
|
||||
|
||||
for i := 0; i < numReaders+numWriters; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkMutexSameReadWrite1(b *testing.B) {
|
||||
benchmarkMutex(b, 1, 1, 32)
|
||||
}
|
||||
func BenchmarkMutexSameReadWrite2(b *testing.B) {
|
||||
benchmarkMutex(b, 2, 2, 32)
|
||||
}
|
||||
func BenchmarkMutexSameReadWrite4(b *testing.B) {
|
||||
benchmarkMutex(b, 4, 4, 32)
|
||||
}
|
||||
func BenchmarkMutex1(b *testing.B) {
|
||||
benchmarkMutex(b, 2, 8, 32)
|
||||
}
|
||||
func BenchmarkMutex2(b *testing.B) {
|
||||
benchmarkMutex(b, 16, 4, 64)
|
||||
}
|
||||
func BenchmarkMutex3(b *testing.B) {
|
||||
benchmarkMutex(b, 1, 2, 128)
|
||||
}
|
||||
func BenchmarkMutex4(b *testing.B) {
|
||||
benchmarkMutex(b, 128, 32, 256)
|
||||
}
|
||||
func BenchmarkMutex5(b *testing.B) {
|
||||
benchmarkMutex(b, 1024, 2048, 64)
|
||||
}
|
||||
func BenchmarkMutex6(b *testing.B) {
|
||||
benchmarkMutex(b, 2048, 1024, 512)
|
||||
}
|
||||
127
vendor/github.com/gorilla/handlers/canonical_test.go
сгенерированный
поставляемый
Обычный файл
127
vendor/github.com/gorilla/handlers/canonical_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,127 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCleanHost(t *testing.T) {
|
||||
tests := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"www.google.com", "www.google.com"},
|
||||
{"www.google.com foo", "www.google.com"},
|
||||
{"www.google.com/foo", "www.google.com"},
|
||||
{" first character is a space", ""},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
got := cleanHost(tt.in)
|
||||
if tt.want != got {
|
||||
t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanonicalHost(t *testing.T) {
|
||||
gorilla := "http://www.gorillatoolkit.org"
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
// Test a re-direct: should return a 302 Found.
|
||||
CanonicalHost(gorilla, http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if rr.Code != http.StatusFound {
|
||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusFound)
|
||||
}
|
||||
|
||||
if rr.Header().Get("Location") != gorilla+r.URL.Path {
|
||||
t.Fatalf("bad re-direct: got %q want %q", rr.Header().Get("Location"), gorilla+r.URL.Path)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestKeepsQueryString(t *testing.T) {
|
||||
google := "https://www.google.com"
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
querystring := url.Values{"q": {"golang"}, "format": {"json"}}.Encode()
|
||||
r := newRequest("GET", "http://www.example.com/search?"+querystring)
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
CanonicalHost(google, http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
want := google + r.URL.Path + "?" + querystring
|
||||
if rr.Header().Get("Location") != want {
|
||||
t.Fatalf("bad re-direct: got %q want %q", rr.Header().Get("Location"), want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadDomain(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
// Test a bad domain - should return 200 OK.
|
||||
CanonicalHost("%", http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyHost(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
// Test a domain that returns an empty url.Host from url.Parse.
|
||||
CanonicalHost("hello.com", http.StatusFound)(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", rr.Code, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeaderWrites(t *testing.T) {
|
||||
gorilla := "http://www.gorillatoolkit.org"
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
// Catch the log output to ensure we don't write multiple headers.
|
||||
var b bytes.Buffer
|
||||
buf := bufio.NewWriter(&b)
|
||||
tl := log.New(buf, "test: ", log.Lshortfile)
|
||||
|
||||
srv := httptest.NewServer(
|
||||
CanonicalHost(gorilla, http.StatusFound)(testHandler))
|
||||
defer srv.Close()
|
||||
srv.Config.ErrorLog = tl
|
||||
|
||||
_, err := http.Get(srv.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = buf.Flush()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// We rely on the error not changing: net/http does not export it.
|
||||
if strings.Contains(b.String(), "multiple response.WriteHeader calls") {
|
||||
t.Fatalf("re-direct did not return early: multiple header writes")
|
||||
}
|
||||
}
|
||||
154
vendor/github.com/gorilla/handlers/compress_test.go
сгенерированный
поставляемый
Обычный файл
154
vendor/github.com/gorilla/handlers/compress_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,154 @@
|
||||
// Copyright 2013 The Gorilla 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 handlers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var contentType = "text/plain; charset=utf-8"
|
||||
|
||||
func compressedRequest(w *httptest.ResponseRecorder, compression string) {
|
||||
CompressHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Length", strconv.Itoa(9*1024))
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
for i := 0; i < 1024; i++ {
|
||||
io.WriteString(w, "Gorilla!\n")
|
||||
}
|
||||
})).ServeHTTP(w, &http.Request{
|
||||
Method: "GET",
|
||||
Header: http.Header{
|
||||
"Accept-Encoding": []string{compression},
|
||||
},
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestCompressHandlerNoCompression(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
compressedRequest(w, "")
|
||||
if enc := w.HeaderMap.Get("Content-Encoding"); enc != "" {
|
||||
t.Errorf("wrong content encoding, got %q want %q", enc, "")
|
||||
}
|
||||
if ct := w.HeaderMap.Get("Content-Type"); ct != contentType {
|
||||
t.Errorf("wrong content type, got %q want %q", ct, contentType)
|
||||
}
|
||||
if w.Body.Len() != 1024*9 {
|
||||
t.Errorf("wrong len, got %d want %d", w.Body.Len(), 1024*9)
|
||||
}
|
||||
if l := w.HeaderMap.Get("Content-Length"); l != "9216" {
|
||||
t.Errorf("wrong content-length. got %q expected %d", l, 1024*9)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressHandlerGzip(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
compressedRequest(w, "gzip")
|
||||
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
|
||||
t.Errorf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "gzip")
|
||||
}
|
||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
||||
t.Errorf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
||||
}
|
||||
if w.Body.Len() != 72 {
|
||||
t.Errorf("wrong len, got %d want %d", w.Body.Len(), 72)
|
||||
}
|
||||
if l := w.HeaderMap.Get("Content-Length"); l != "" {
|
||||
t.Errorf("wrong content-length. got %q expected %q", l, "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressHandlerDeflate(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
compressedRequest(w, "deflate")
|
||||
if w.HeaderMap.Get("Content-Encoding") != "deflate" {
|
||||
t.Fatalf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "deflate")
|
||||
}
|
||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
||||
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
||||
}
|
||||
if w.Body.Len() != 54 {
|
||||
t.Fatalf("wrong len, got %d want %d", w.Body.Len(), 54)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressHandlerGzipDeflate(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
compressedRequest(w, "gzip, deflate ")
|
||||
if w.HeaderMap.Get("Content-Encoding") != "gzip" {
|
||||
t.Fatalf("wrong content encoding, got %q want %q", w.HeaderMap.Get("Content-Encoding"), "gzip")
|
||||
}
|
||||
if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
|
||||
t.Fatalf("wrong content type, got %s want %s", w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
||||
}
|
||||
}
|
||||
|
||||
type fullyFeaturedResponseWriter struct{}
|
||||
|
||||
// Header/Write/WriteHeader implement the http.ResponseWriter interface.
|
||||
func (fullyFeaturedResponseWriter) Header() http.Header {
|
||||
return http.Header{}
|
||||
}
|
||||
func (fullyFeaturedResponseWriter) Write([]byte) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
func (fullyFeaturedResponseWriter) WriteHeader(int) {}
|
||||
|
||||
// Flush implements the http.Flusher interface.
|
||||
func (fullyFeaturedResponseWriter) Flush() {}
|
||||
|
||||
// Hijack implements the http.Hijacker interface.
|
||||
func (fullyFeaturedResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// CloseNotify implements the http.CloseNotifier interface.
|
||||
func (fullyFeaturedResponseWriter) CloseNotify() <-chan bool {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestCompressHandlerPreserveInterfaces(t *testing.T) {
|
||||
// Compile time validation fullyFeaturedResponseWriter implements all the
|
||||
// interfaces we're asserting in the test case below.
|
||||
var (
|
||||
_ http.Flusher = fullyFeaturedResponseWriter{}
|
||||
_ http.CloseNotifier = fullyFeaturedResponseWriter{}
|
||||
_ http.Hijacker = fullyFeaturedResponseWriter{}
|
||||
)
|
||||
var h http.Handler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
comp := r.Header.Get("Accept-Encoding")
|
||||
if _, ok := rw.(*compressResponseWriter); !ok {
|
||||
t.Fatalf("ResponseWriter wasn't wrapped by compressResponseWriter, got %T type", rw)
|
||||
}
|
||||
if _, ok := rw.(http.Flusher); !ok {
|
||||
t.Errorf("ResponseWriter lost http.Flusher interface for %q", comp)
|
||||
}
|
||||
if _, ok := rw.(http.CloseNotifier); !ok {
|
||||
t.Errorf("ResponseWriter lost http.CloseNotifier interface for %q", comp)
|
||||
}
|
||||
if _, ok := rw.(http.Hijacker); !ok {
|
||||
t.Errorf("ResponseWriter lost http.Hijacker interface for %q", comp)
|
||||
}
|
||||
})
|
||||
h = CompressHandler(h)
|
||||
var (
|
||||
rw fullyFeaturedResponseWriter
|
||||
)
|
||||
r, err := http.NewRequest("GET", "/", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test request: %v", err)
|
||||
}
|
||||
r.Header.Set("Accept-Encoding", "gzip")
|
||||
h.ServeHTTP(rw, r)
|
||||
|
||||
r.Header.Set("Accept-Encoding", "deflate")
|
||||
h.ServeHTTP(rw, r)
|
||||
}
|
||||
336
vendor/github.com/gorilla/handlers/cors_test.go
сгенерированный
поставляемый
Обычный файл
336
vendor/github.com/gorilla/handlers/cors_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,336 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDefaultCORSHandlerReturnsOk(t *testing.T) {
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultCORSHandlerReturnsOkWithOrigin(t *testing.T) {
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerIgnoreOptionsFallsThrough(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
|
||||
CORS(IgnoreOptions())(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusTeapot {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusTeapot)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerSetsExposedHeaders(t *testing.T) {
|
||||
// Test default configuration.
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(ExposedHeaders([]string{"X-CORS-TEST"}))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsExposeHeadersHeader)
|
||||
if header != "X-Cors-Test" {
|
||||
t.Fatal("bad header: expected X-Cors-Test header, got empty header for method.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerUnsetRequestMethodForPreflightBadRequest(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(AllowedMethods([]string{"DELETE"}))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusBadRequest {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerInvalidRequestMethodForPreflightMethodNotAllowed(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "DELETE")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusMethodNotAllowed {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerOptionsRequestMustNotBePassedToNextHandler(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "GET")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("Options request must not be passed to next handler")
|
||||
})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerAllowedMethodForPreflight(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "DELETE")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(AllowedMethods([]string{"DELETE"}))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsAllowMethodsHeader)
|
||||
if header != "DELETE" {
|
||||
t.Fatalf("bad header: expected DELETE method header, got empty header.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerAllowMethodsNotSetForSimpleRequestPreflight(t *testing.T) {
|
||||
for _, method := range defaultCorsMethods {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, method)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsAllowMethodsHeader)
|
||||
if header != "" {
|
||||
t.Fatalf("bad header: expected empty method header, got %s.", header)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerAllowedHeaderNotSetForSimpleRequestPreflight(t *testing.T) {
|
||||
for _, simpleHeader := range defaultCorsHeaders {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "GET")
|
||||
r.Header.Set(corsRequestHeadersHeader, simpleHeader)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsAllowHeadersHeader)
|
||||
if header != "" {
|
||||
t.Fatalf("bad header: expected empty header, got %s.", header)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerAllowedHeaderForPreflight(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "POST")
|
||||
r.Header.Set(corsRequestHeadersHeader, "Content-Type")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(AllowedHeaders([]string{"Content-Type"}))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsAllowHeadersHeader)
|
||||
if header != "Content-Type" {
|
||||
t.Fatalf("bad header: expected Content-Type header, got empty header.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerInvalidHeaderForPreflightForbidden(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "POST")
|
||||
r.Header.Set(corsRequestHeadersHeader, "Content-Type")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS()(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusForbidden {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerMaxAgeForPreflight(t *testing.T) {
|
||||
r := newRequest("OPTIONS", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
r.Header.Set(corsRequestMethodHeader, "POST")
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(MaxAge(3500))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsMaxAgeHeader)
|
||||
if header != "600" {
|
||||
t.Fatalf("bad header: expected %s to be %s, got %s.", corsMaxAgeHeader, "600", header)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerAllowedCredentials(t *testing.T) {
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(AllowCredentials())(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsAllowCredentialsHeader)
|
||||
if header != "true" {
|
||||
t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowCredentialsHeader, "true", header)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerMultipleAllowOriginsSetsVaryHeader(t *testing.T) {
|
||||
r := newRequest("GET", "http://www.example.com/")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
CORS(AllowedOrigins([]string{r.URL.String(), "http://google.com"}))(testHandler).ServeHTTP(rr, r)
|
||||
|
||||
if status := rr.Code; status != http.StatusOK {
|
||||
t.Fatalf("bad status: got %v want %v", status, http.StatusOK)
|
||||
}
|
||||
|
||||
header := rr.HeaderMap.Get(corsVaryHeader)
|
||||
if header != corsOriginHeader {
|
||||
t.Fatalf("bad header: expected %s to be %s, got %s.", corsVaryHeader, corsOriginHeader, header)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSWithMultipleHandlers(t *testing.T) {
|
||||
var lastHandledBy string
|
||||
corsMiddleware := CORS()
|
||||
|
||||
testHandler1 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
lastHandledBy = "testHandler1"
|
||||
})
|
||||
testHandler2 := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
lastHandledBy = "testHandler2"
|
||||
})
|
||||
|
||||
r1 := newRequest("GET", "http://www.example.com/")
|
||||
rr1 := httptest.NewRecorder()
|
||||
handler1 := corsMiddleware(testHandler1)
|
||||
|
||||
corsMiddleware(testHandler2)
|
||||
|
||||
handler1.ServeHTTP(rr1, r1)
|
||||
if lastHandledBy != "testHandler1" {
|
||||
t.Fatalf("bad CORS() registration: Handler served should be Handler registered")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCORSHandlerWithCustomValidator(t *testing.T) {
|
||||
r := newRequest("GET", "http://a.example.com")
|
||||
r.Header.Set("Origin", r.URL.String())
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
|
||||
originValidator := func(origin string) bool {
|
||||
if strings.HasSuffix(origin, ".example.com") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r)
|
||||
header := rr.HeaderMap.Get(corsAllowOriginHeader)
|
||||
if header != r.URL.String() {
|
||||
t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
|
||||
}
|
||||
|
||||
}
|
||||
354
vendor/github.com/gorilla/handlers/handlers_test.go
сгенерированный
поставляемый
Обычный файл
354
vendor/github.com/gorilla/handlers/handlers_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,354 @@
|
||||
// Copyright 2013 The Gorilla 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 handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
ok = "ok\n"
|
||||
notAllowed = "Method not allowed\n"
|
||||
)
|
||||
|
||||
var okHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte(ok))
|
||||
})
|
||||
|
||||
func newRequest(method, url string) *http.Request {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func TestMethodHandler(t *testing.T) {
|
||||
tests := []struct {
|
||||
req *http.Request
|
||||
handler http.Handler
|
||||
code int
|
||||
allow string // Contents of the Allow header
|
||||
body string
|
||||
}{
|
||||
// No handlers
|
||||
{newRequest("GET", "/foo"), MethodHandler{}, http.StatusMethodNotAllowed, "", notAllowed},
|
||||
{newRequest("OPTIONS", "/foo"), MethodHandler{}, http.StatusOK, "", ""},
|
||||
|
||||
// A single handler
|
||||
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler}, http.StatusOK, "", ok},
|
||||
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler}, http.StatusMethodNotAllowed, "GET", notAllowed},
|
||||
|
||||
// Multiple handlers
|
||||
{newRequest("GET", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
|
||||
{newRequest("POST", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "", ok},
|
||||
{newRequest("DELETE", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusMethodNotAllowed, "GET, POST", notAllowed},
|
||||
{newRequest("OPTIONS", "/foo"), MethodHandler{"GET": okHandler, "POST": okHandler}, http.StatusOK, "GET, POST", ""},
|
||||
|
||||
// Override OPTIONS
|
||||
{newRequest("OPTIONS", "/foo"), MethodHandler{"OPTIONS": okHandler}, http.StatusOK, "", ok},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
rec := httptest.NewRecorder()
|
||||
test.handler.ServeHTTP(rec, test.req)
|
||||
if rec.Code != test.code {
|
||||
t.Fatalf("%d: wrong code, got %d want %d", i, rec.Code, test.code)
|
||||
}
|
||||
if allow := rec.HeaderMap.Get("Allow"); allow != test.allow {
|
||||
t.Fatalf("%d: wrong Allow, got %s want %s", i, allow, test.allow)
|
||||
}
|
||||
if body := rec.Body.String(); body != test.body {
|
||||
t.Fatalf("%d: wrong body, got %q want %q", i, body, test.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteLog(t *testing.T) {
|
||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
||||
|
||||
// A typical request with an OK response
|
||||
req := newRequest("GET", "http://example.com")
|
||||
req.RemoteAddr = "192.168.100.5"
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log := buf.String()
|
||||
|
||||
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// CONNECT request over http/2.0
|
||||
req = &http.Request{
|
||||
Method: "CONNECT",
|
||||
Proto: "HTTP/2.0",
|
||||
ProtoMajor: 2,
|
||||
ProtoMinor: 0,
|
||||
URL: &url.URL{Host: "www.example.com:443"},
|
||||
Host: "www.example.com:443",
|
||||
RemoteAddr: "192.168.100.5",
|
||||
}
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log = buf.String()
|
||||
|
||||
expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"CONNECT www.example.com:443 HTTP/2.0\" 200 100\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// Request with an unauthorized user
|
||||
req = newRequest("GET", "http://example.com")
|
||||
req.RemoteAddr = "192.168.100.5"
|
||||
req.URL.User = url.User("kamil")
|
||||
|
||||
buf.Reset()
|
||||
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
||||
log = buf.String()
|
||||
|
||||
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// Request with url encoded parameters
|
||||
req = newRequest("GET", "http://example.com/test?abc=hello%20world&a=b%3F")
|
||||
req.RemoteAddr = "192.168.100.5"
|
||||
|
||||
buf.Reset()
|
||||
writeLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log = buf.String()
|
||||
|
||||
expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET /test?abc=hello%20world&a=b%3F HTTP/1.1\" 200 100\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteCombinedLog(t *testing.T) {
|
||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
||||
|
||||
// A typical request with an OK response
|
||||
req := newRequest("GET", "http://example.com")
|
||||
req.RemoteAddr = "192.168.100.5"
|
||||
req.Header.Set("Referer", "http://example.com")
|
||||
req.Header.Set(
|
||||
"User-Agent",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+
|
||||
"(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33",
|
||||
)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log := buf.String()
|
||||
|
||||
expected := "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// CONNECT request over http/2.0
|
||||
req1 := &http.Request{
|
||||
Method: "CONNECT",
|
||||
Host: "www.example.com:443",
|
||||
Proto: "HTTP/2.0",
|
||||
ProtoMajor: 2,
|
||||
ProtoMinor: 0,
|
||||
RemoteAddr: "192.168.100.5",
|
||||
Header: http.Header{},
|
||||
URL: &url.URL{Host: "www.example.com:443"},
|
||||
}
|
||||
req1.Header.Set("Referer", "http://example.com")
|
||||
req1.Header.Set(
|
||||
"User-Agent",
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.33 "+
|
||||
"(KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33",
|
||||
)
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
writeCombinedLog(buf, req1, *req1.URL, ts, http.StatusOK, 100)
|
||||
log = buf.String()
|
||||
|
||||
expected = "192.168.100.5 - - [26/May/1983:03:30:45 +0200] \"CONNECT www.example.com:443 HTTP/2.0\" 200 100 \"http://example.com\" " +
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// Request with an unauthorized user
|
||||
req.URL.User = url.User("kamil")
|
||||
|
||||
buf.Reset()
|
||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
||||
log = buf.String()
|
||||
|
||||
expected = "192.168.100.5 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 401 500 \"http://example.com\" " +
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// Test with remote ipv6 address
|
||||
req.RemoteAddr = "::1"
|
||||
|
||||
buf.Reset()
|
||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log = buf.String()
|
||||
|
||||
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
|
||||
// Test remote ipv6 addr, with port
|
||||
req.RemoteAddr = net.JoinHostPort("::1", "65000")
|
||||
|
||||
buf.Reset()
|
||||
writeCombinedLog(buf, req, *req.URL, ts, http.StatusOK, 100)
|
||||
log = buf.String()
|
||||
|
||||
expected = "::1 - kamil [26/May/1983:03:30:45 +0200] \"GET / HTTP/1.1\" 200 100 \"http://example.com\" " +
|
||||
"\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) " +
|
||||
"AppleWebKit/537.33 (KHTML, like Gecko) Chrome/27.0.1430.0 Safari/537.33\"\n"
|
||||
if log != expected {
|
||||
t.Fatalf("wrong log, got %q want %q", log, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogPathRewrites(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
req.URL.Path = "/" // simulate http.StripPrefix and friends
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
logger := LoggingHandler(&buf, handler)
|
||||
|
||||
logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf"))
|
||||
|
||||
if !strings.Contains(buf.String(), "GET /subdir/asdf HTTP") {
|
||||
t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "GET /subdir/asdf HTTP")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkWriteLog(b *testing.B) {
|
||||
loc, err := time.LoadLocation("Europe/Warsaw")
|
||||
if err != nil {
|
||||
b.Fatalf(err.Error())
|
||||
}
|
||||
ts := time.Date(1983, 05, 26, 3, 30, 45, 0, loc)
|
||||
|
||||
req := newRequest("GET", "http://example.com")
|
||||
req.RemoteAddr = "192.168.100.5"
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
for i := 0; i < b.N; i++ {
|
||||
buf.Reset()
|
||||
writeLog(buf, req, *req.URL, ts, http.StatusUnauthorized, 500)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentTypeHandler(t *testing.T) {
|
||||
tests := []struct {
|
||||
Method string
|
||||
AllowContentTypes []string
|
||||
ContentType string
|
||||
Code int
|
||||
}{
|
||||
{"POST", []string{"application/json"}, "application/json", http.StatusOK},
|
||||
{"POST", []string{"application/json", "application/xml"}, "application/json", http.StatusOK},
|
||||
{"POST", []string{"application/json"}, "application/json; charset=utf-8", http.StatusOK},
|
||||
{"POST", []string{"application/json"}, "application/json+xxx", http.StatusUnsupportedMediaType},
|
||||
{"POST", []string{"application/json"}, "text/plain", http.StatusUnsupportedMediaType},
|
||||
{"GET", []string{"application/json"}, "", http.StatusOK},
|
||||
{"GET", []string{}, "", http.StatusOK},
|
||||
}
|
||||
for _, test := range tests {
|
||||
r, err := http.NewRequest(test.Method, "/", nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
h := ContentTypeHandler(okHandler, test.AllowContentTypes...)
|
||||
r.Header.Set("Content-Type", test.ContentType)
|
||||
w := httptest.NewRecorder()
|
||||
h.ServeHTTP(w, r)
|
||||
if w.Code != test.Code {
|
||||
t.Errorf("expected %d, got %d", test.Code, w.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPMethodOverride(t *testing.T) {
|
||||
var tests = []struct {
|
||||
Method string
|
||||
OverrideMethod string
|
||||
ExpectedMethod string
|
||||
}{
|
||||
{"POST", "PUT", "PUT"},
|
||||
{"POST", "PATCH", "PATCH"},
|
||||
{"POST", "DELETE", "DELETE"},
|
||||
{"PUT", "DELETE", "PUT"},
|
||||
{"GET", "GET", "GET"},
|
||||
{"HEAD", "HEAD", "HEAD"},
|
||||
{"GET", "PUT", "GET"},
|
||||
{"HEAD", "DELETE", "HEAD"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
h := HTTPMethodOverrideHandler(okHandler)
|
||||
reqs := make([]*http.Request, 0, 2)
|
||||
|
||||
rHeader, err := http.NewRequest(test.Method, "/", nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rHeader.Header.Set(HTTPMethodOverrideHeader, test.OverrideMethod)
|
||||
reqs = append(reqs, rHeader)
|
||||
|
||||
f := url.Values{HTTPMethodOverrideFormKey: []string{test.OverrideMethod}}
|
||||
rForm, err := http.NewRequest(test.Method, "/", strings.NewReader(f.Encode()))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
rForm.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
reqs = append(reqs, rForm)
|
||||
|
||||
for _, r := range reqs {
|
||||
w := httptest.NewRecorder()
|
||||
h.ServeHTTP(w, r)
|
||||
if r.Method != test.ExpectedMethod {
|
||||
t.Errorf("Expected %s, got %s", test.ExpectedMethod, r.Method)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
vendor/github.com/gorilla/handlers/proxy_headers_test.go
сгенерированный
поставляемый
Обычный файл
100
vendor/github.com/gorilla/handlers/proxy_headers_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,100 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type headerTable struct {
|
||||
key string // header key
|
||||
val string // header val
|
||||
expected string // expected result
|
||||
}
|
||||
|
||||
func TestGetIP(t *testing.T) {
|
||||
headers := []headerTable{
|
||||
{xForwardedFor, "8.8.8.8", "8.8.8.8"}, // Single address
|
||||
{xForwardedFor, "8.8.8.8, 8.8.4.4", "8.8.8.8"}, // Multiple
|
||||
{xForwardedFor, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address
|
||||
{xForwardedFor, "", ""}, // None
|
||||
{xRealIP, "8.8.8.8", "8.8.8.8"}, // Single address
|
||||
{xRealIP, "8.8.8.8, 8.8.4.4", "8.8.8.8, 8.8.4.4"}, // Multiple
|
||||
{xRealIP, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address
|
||||
{xRealIP, "", ""}, // None
|
||||
{forwarded, `for="_gazonk"`, "_gazonk"}, // Hostname
|
||||
{forwarded, `For="[2001:db8:cafe::17]:4711`, `[2001:db8:cafe::17]:4711`}, // IPv6 address
|
||||
{forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, `192.0.2.60`}, // Multiple params
|
||||
{forwarded, `for=192.0.2.43, for=198.51.100.17`, "192.0.2.43"}, // Multiple params
|
||||
{forwarded, `for="workstation.local",for=198.51.100.17`, "workstation.local"}, // Hostname
|
||||
}
|
||||
|
||||
for _, v := range headers {
|
||||
req := &http.Request{
|
||||
Header: http.Header{
|
||||
v.key: []string{v.val},
|
||||
}}
|
||||
res := getIP(req)
|
||||
if res != v.expected {
|
||||
t.Fatalf("wrong header for %s: got %s want %s", v.key, res,
|
||||
v.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetScheme(t *testing.T) {
|
||||
headers := []headerTable{
|
||||
{xForwardedProto, "https", "https"},
|
||||
{xForwardedProto, "http", "http"},
|
||||
{xForwardedProto, "HTTP", "http"},
|
||||
{forwarded, `For="[2001:db8:cafe::17]:4711`, ""}, // No proto
|
||||
{forwarded, `for=192.0.2.43, for=198.51.100.17;proto=https`, "https"}, // Multiple params before proto
|
||||
{forwarded, `for=172.32.10.15; proto=https;by=127.0.0.1`, "https"}, // Space before proto
|
||||
{forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, "http"}, // Multiple params
|
||||
}
|
||||
|
||||
for _, v := range headers {
|
||||
req := &http.Request{
|
||||
Header: http.Header{
|
||||
v.key: []string{v.val},
|
||||
},
|
||||
}
|
||||
res := getScheme(req)
|
||||
if res != v.expected {
|
||||
t.Fatalf("wrong header for %s: got %s want %s", v.key, res,
|
||||
v.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the middleware end-to-end
|
||||
func TestProxyHeaders(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
r := newRequest("GET", "/")
|
||||
|
||||
r.Header.Set(xForwardedFor, "8.8.8.8")
|
||||
r.Header.Set(xForwardedProto, "https")
|
||||
|
||||
var addr string
|
||||
var proto string
|
||||
ProxyHeaders(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
addr = r.RemoteAddr
|
||||
proto = r.URL.Scheme
|
||||
})).ServeHTTP(rr, r)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("bad status: got %d want %d", rr.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
if addr != r.Header.Get(xForwardedFor) {
|
||||
t.Fatalf("wrong address: got %s want %s", addr,
|
||||
r.Header.Get(xForwardedFor))
|
||||
}
|
||||
|
||||
if proto != r.Header.Get(xForwardedProto) {
|
||||
t.Fatalf("wrong address: got %s want %s", proto,
|
||||
r.Header.Get(xForwardedProto))
|
||||
}
|
||||
|
||||
}
|
||||
44
vendor/github.com/gorilla/handlers/recovery_test.go
сгенерированный
поставляемый
Обычный файл
44
vendor/github.com/gorilla/handlers/recovery_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,44 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRecoveryLoggerWithDefaultOptions(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
log.SetOutput(&buf)
|
||||
|
||||
handler := RecoveryHandler()
|
||||
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
panic("Unexpected error!")
|
||||
})
|
||||
|
||||
recovery := handler(handlerFunc)
|
||||
recovery.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf"))
|
||||
|
||||
if !strings.Contains(buf.String(), "Unexpected error!") {
|
||||
t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "Unexpected error!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecoveryLoggerWithCustomLogger(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
var logger = log.New(&buf, "", log.LstdFlags)
|
||||
|
||||
handler := RecoveryHandler(RecoveryLogger(logger), PrintRecoveryStack(false))
|
||||
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
panic("Unexpected error!")
|
||||
})
|
||||
|
||||
recovery := handler(handlerFunc)
|
||||
recovery.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/subdir/asdf"))
|
||||
|
||||
if !strings.Contains(buf.String(), "Unexpected error!") {
|
||||
t.Fatalf("Got log %#v, wanted substring %#v", buf.String(), "Unexpected error!")
|
||||
}
|
||||
}
|
||||
49
vendor/github.com/gorilla/mux/bench_test.go
сгенерированный
поставляемый
Обычный файл
49
vendor/github.com/gorilla/mux/bench_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,49 @@
|
||||
// Copyright 2012 The Gorilla 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 mux
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMux(b *testing.B) {
|
||||
router := new(Router)
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {}
|
||||
router.HandleFunc("/v1/{v1}", handler)
|
||||
|
||||
request, _ := http.NewRequest("GET", "/v1/anything", nil)
|
||||
for i := 0; i < b.N; i++ {
|
||||
router.ServeHTTP(nil, request)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMuxAlternativeInRegexp(b *testing.B) {
|
||||
router := new(Router)
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {}
|
||||
router.HandleFunc("/v1/{v1:(a|b)}", handler)
|
||||
|
||||
requestA, _ := http.NewRequest("GET", "/v1/a", nil)
|
||||
requestB, _ := http.NewRequest("GET", "/v1/b", nil)
|
||||
for i := 0; i < b.N; i++ {
|
||||
router.ServeHTTP(nil, requestA)
|
||||
router.ServeHTTP(nil, requestB)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkManyPathVariables(b *testing.B) {
|
||||
router := new(Router)
|
||||
handler := func(w http.ResponseWriter, r *http.Request) {}
|
||||
router.HandleFunc("/v1/{v1}/{v2}/{v3}/{v4}/{v5}", handler)
|
||||
|
||||
matchingRequest, _ := http.NewRequest("GET", "/v1/1/2/3/4/5", nil)
|
||||
notMatchingRequest, _ := http.NewRequest("GET", "/v1/1/2/3/4", nil)
|
||||
recorder := httptest.NewRecorder()
|
||||
for i := 0; i < b.N; i++ {
|
||||
router.ServeHTTP(nil, matchingRequest)
|
||||
router.ServeHTTP(recorder, notMatchingRequest)
|
||||
}
|
||||
}
|
||||
1471
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
Обычный файл
1471
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
710
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
Обычный файл
710
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,710 @@
|
||||
// Old tests ported to Go1. This is a mess. Want to drop it one day.
|
||||
|
||||
// Copyright 2011 Gorilla 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 mux
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ResponseRecorder
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// ResponseRecorder is an implementation of http.ResponseWriter that
|
||||
// records its mutations for later inspection in tests.
|
||||
type ResponseRecorder struct {
|
||||
Code int // the HTTP response code from WriteHeader
|
||||
HeaderMap http.Header // the HTTP response headers
|
||||
Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
|
||||
Flushed bool
|
||||
}
|
||||
|
||||
// NewRecorder returns an initialized ResponseRecorder.
|
||||
func NewRecorder() *ResponseRecorder {
|
||||
return &ResponseRecorder{
|
||||
HeaderMap: make(http.Header),
|
||||
Body: new(bytes.Buffer),
|
||||
}
|
||||
}
|
||||
|
||||
// Header returns the response headers.
|
||||
func (rw *ResponseRecorder) Header() http.Header {
|
||||
return rw.HeaderMap
|
||||
}
|
||||
|
||||
// Write always succeeds and writes to rw.Body, if not nil.
|
||||
func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
|
||||
if rw.Body != nil {
|
||||
rw.Body.Write(buf)
|
||||
}
|
||||
if rw.Code == 0 {
|
||||
rw.Code = http.StatusOK
|
||||
}
|
||||
return len(buf), nil
|
||||
}
|
||||
|
||||
// WriteHeader sets rw.Code.
|
||||
func (rw *ResponseRecorder) WriteHeader(code int) {
|
||||
rw.Code = code
|
||||
}
|
||||
|
||||
// Flush sets rw.Flushed to true.
|
||||
func (rw *ResponseRecorder) Flush() {
|
||||
rw.Flushed = true
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func TestRouteMatchers(t *testing.T) {
|
||||
var scheme, host, path, query, method string
|
||||
var headers map[string]string
|
||||
var resultVars map[bool]map[string]string
|
||||
|
||||
router := NewRouter()
|
||||
router.NewRoute().Host("{var1}.google.com").
|
||||
Path("/{var2:[a-z]+}/{var3:[0-9]+}").
|
||||
Queries("foo", "bar").
|
||||
Methods("GET").
|
||||
Schemes("https").
|
||||
Headers("x-requested-with", "XMLHttpRequest")
|
||||
router.NewRoute().Host("www.{var4}.com").
|
||||
PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
|
||||
Queries("baz", "ding").
|
||||
Methods("POST").
|
||||
Schemes("http").
|
||||
Headers("Content-Type", "application/json")
|
||||
|
||||
reset := func() {
|
||||
// Everything match.
|
||||
scheme = "https"
|
||||
host = "www.google.com"
|
||||
path = "/product/42"
|
||||
query = "?foo=bar"
|
||||
method = "GET"
|
||||
headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
|
||||
resultVars = map[bool]map[string]string{
|
||||
true: {"var1": "www", "var2": "product", "var3": "42"},
|
||||
false: {},
|
||||
}
|
||||
}
|
||||
|
||||
reset2 := func() {
|
||||
// Everything match.
|
||||
scheme = "http"
|
||||
host = "www.google.com"
|
||||
path = "/foo/product/42/path/that/is/ignored"
|
||||
query = "?baz=ding"
|
||||
method = "POST"
|
||||
headers = map[string]string{"Content-Type": "application/json"}
|
||||
resultVars = map[bool]map[string]string{
|
||||
true: {"var4": "google", "var5": "product", "var6": "42"},
|
||||
false: {},
|
||||
}
|
||||
}
|
||||
|
||||
match := func(shouldMatch bool) {
|
||||
url := scheme + "://" + host + path + query
|
||||
request, _ := http.NewRequest(method, url, nil)
|
||||
for key, value := range headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
|
||||
var routeMatch RouteMatch
|
||||
matched := router.Match(request, &routeMatch)
|
||||
if matched != shouldMatch {
|
||||
// Need better messages. :)
|
||||
if matched {
|
||||
t.Errorf("Should match.")
|
||||
} else {
|
||||
t.Errorf("Should not match.")
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
currentRoute := routeMatch.Route
|
||||
if currentRoute == nil {
|
||||
t.Errorf("Expected a current route.")
|
||||
}
|
||||
vars := routeMatch.Vars
|
||||
expectedVars := resultVars[shouldMatch]
|
||||
if len(vars) != len(expectedVars) {
|
||||
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
||||
}
|
||||
for name, value := range vars {
|
||||
if expectedVars[name] != value {
|
||||
t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1st route --------------------------------------------------------------
|
||||
|
||||
// Everything match.
|
||||
reset()
|
||||
match(true)
|
||||
|
||||
// Scheme doesn't match.
|
||||
reset()
|
||||
scheme = "http"
|
||||
match(false)
|
||||
|
||||
// Host doesn't match.
|
||||
reset()
|
||||
host = "www.mygoogle.com"
|
||||
match(false)
|
||||
|
||||
// Path doesn't match.
|
||||
reset()
|
||||
path = "/product/notdigits"
|
||||
match(false)
|
||||
|
||||
// Query doesn't match.
|
||||
reset()
|
||||
query = "?foo=baz"
|
||||
match(false)
|
||||
|
||||
// Method doesn't match.
|
||||
reset()
|
||||
method = "POST"
|
||||
match(false)
|
||||
|
||||
// Header doesn't match.
|
||||
reset()
|
||||
headers = map[string]string{}
|
||||
match(false)
|
||||
|
||||
// Everything match, again.
|
||||
reset()
|
||||
match(true)
|
||||
|
||||
// 2nd route --------------------------------------------------------------
|
||||
|
||||
// Everything match.
|
||||
reset2()
|
||||
match(true)
|
||||
|
||||
// Scheme doesn't match.
|
||||
reset2()
|
||||
scheme = "https"
|
||||
match(false)
|
||||
|
||||
// Host doesn't match.
|
||||
reset2()
|
||||
host = "sub.google.com"
|
||||
match(false)
|
||||
|
||||
// Path doesn't match.
|
||||
reset2()
|
||||
path = "/bar/product/42"
|
||||
match(false)
|
||||
|
||||
// Query doesn't match.
|
||||
reset2()
|
||||
query = "?foo=baz"
|
||||
match(false)
|
||||
|
||||
// Method doesn't match.
|
||||
reset2()
|
||||
method = "GET"
|
||||
match(false)
|
||||
|
||||
// Header doesn't match.
|
||||
reset2()
|
||||
headers = map[string]string{}
|
||||
match(false)
|
||||
|
||||
// Everything match, again.
|
||||
reset2()
|
||||
match(true)
|
||||
}
|
||||
|
||||
type headerMatcherTest struct {
|
||||
matcher headerMatcher
|
||||
headers map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var headerMatcherTests = []headerMatcherTest{
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
||||
headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
|
||||
headers: map[string]string{"X-Requested-With": "anything"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
|
||||
headers: map[string]string{},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type hostMatcherTest struct {
|
||||
matcher *Route
|
||||
url string
|
||||
vars map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var hostMatcherTests = []hostMatcherTest{
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
|
||||
url: "http://abc.def.ghi/",
|
||||
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
|
||||
url: "http://a.b.c/",
|
||||
vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type methodMatcherTest struct {
|
||||
matcher methodMatcher
|
||||
method string
|
||||
result bool
|
||||
}
|
||||
|
||||
var methodMatcherTests = []methodMatcherTest{
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "GET",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "POST",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "PUT",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
|
||||
method: "DELETE",
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type pathMatcherTest struct {
|
||||
matcher *Route
|
||||
url string
|
||||
vars map[string]string
|
||||
result bool
|
||||
}
|
||||
|
||||
var pathMatcherTests = []pathMatcherTest{
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
|
||||
url: "http://localhost:8080/123/456/789",
|
||||
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
|
||||
url: "http://localhost:8080/1/2/3",
|
||||
vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"},
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type schemeMatcherTest struct {
|
||||
matcher schemeMatcher
|
||||
url string
|
||||
result bool
|
||||
}
|
||||
|
||||
var schemeMatcherTests = []schemeMatcherTest{
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http", "https"}),
|
||||
url: "http://localhost:8080/",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http", "https"}),
|
||||
url: "https://localhost:8080/",
|
||||
result: true,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"https"}),
|
||||
url: "http://localhost:8080/",
|
||||
result: false,
|
||||
},
|
||||
{
|
||||
matcher: schemeMatcher([]string{"http"}),
|
||||
url: "https://localhost:8080/",
|
||||
result: false,
|
||||
},
|
||||
}
|
||||
|
||||
type urlBuildingTest struct {
|
||||
route *Route
|
||||
vars []string
|
||||
url string
|
||||
}
|
||||
|
||||
var urlBuildingTests = []urlBuildingTest{
|
||||
{
|
||||
route: new(Route).Host("foo.domain.com"),
|
||||
vars: []string{},
|
||||
url: "http://foo.domain.com",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("{subdomain}.domain.com"),
|
||||
vars: []string{"subdomain", "bar"},
|
||||
url: "http://bar.domain.com",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("foo.domain.com").Path("/articles"),
|
||||
vars: []string{},
|
||||
url: "http://foo.domain.com/articles",
|
||||
},
|
||||
{
|
||||
route: new(Route).Path("/articles"),
|
||||
vars: []string{},
|
||||
url: "/articles",
|
||||
},
|
||||
{
|
||||
route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
|
||||
vars: []string{"category", "technology", "id", "42"},
|
||||
url: "/articles/technology/42",
|
||||
},
|
||||
{
|
||||
route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
|
||||
vars: []string{"subdomain", "foo", "category", "technology", "id", "42"},
|
||||
url: "http://foo.domain.com/articles/technology/42",
|
||||
},
|
||||
}
|
||||
|
||||
func TestHeaderMatcher(t *testing.T) {
|
||||
for _, v := range headerMatcherTests {
|
||||
request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
|
||||
for key, value := range v.headers {
|
||||
request.Header.Add(key, value)
|
||||
}
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, request.Header)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostMatcher(t *testing.T) {
|
||||
for _, v := range hostMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
if result {
|
||||
if len(vars) != len(v.vars) {
|
||||
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
||||
}
|
||||
for name, value := range vars {
|
||||
if v.vars[name] != value {
|
||||
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(vars) != 0 {
|
||||
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMethodMatcher(t *testing.T) {
|
||||
for _, v := range methodMatcherTests {
|
||||
request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.method)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.method)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathMatcher(t *testing.T) {
|
||||
for _, v := range pathMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
if result {
|
||||
if len(vars) != len(v.vars) {
|
||||
t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
|
||||
}
|
||||
for name, value := range vars {
|
||||
if v.vars[name] != value {
|
||||
t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(vars) != 0 {
|
||||
t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchemeMatcher(t *testing.T) {
|
||||
for _, v := range schemeMatcherTests {
|
||||
request, _ := http.NewRequest("GET", v.url, nil)
|
||||
var routeMatch RouteMatch
|
||||
result := v.matcher.Match(request, &routeMatch)
|
||||
if result != v.result {
|
||||
if v.result {
|
||||
t.Errorf("%#v: should match %v.", v.matcher, v.url)
|
||||
} else {
|
||||
t.Errorf("%#v: should not match %v.", v.matcher, v.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUrlBuilding(t *testing.T) {
|
||||
|
||||
for _, v := range urlBuildingTests {
|
||||
u, _ := v.route.URL(v.vars...)
|
||||
url := u.String()
|
||||
if url != v.url {
|
||||
t.Errorf("expected %v, got %v", v.url, url)
|
||||
/*
|
||||
reversePath := ""
|
||||
reverseHost := ""
|
||||
if v.route.pathTemplate != nil {
|
||||
reversePath = v.route.pathTemplate.Reverse
|
||||
}
|
||||
if v.route.hostTemplate != nil {
|
||||
reverseHost = v.route.hostTemplate.Reverse
|
||||
}
|
||||
|
||||
t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
|
||||
|
||||
url, _ := router.Get("article").URL("category", "technology", "id", "42")
|
||||
expected := "/articles/technology/42"
|
||||
if url.String() != expected {
|
||||
t.Errorf("Expected %v, got %v", expected, url.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchedRouteName(t *testing.T) {
|
||||
routeName := "stock"
|
||||
router := NewRouter()
|
||||
route := router.NewRoute().Path("/products/").Name(routeName)
|
||||
|
||||
url := "http://www.example.com/products/"
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
var rv RouteMatch
|
||||
ok := router.Match(request, &rv)
|
||||
|
||||
if !ok || rv.Route != route {
|
||||
t.Errorf("Expected same route, got %+v.", rv.Route)
|
||||
}
|
||||
|
||||
retName := rv.Route.GetName()
|
||||
if retName != routeName {
|
||||
t.Errorf("Expected %q, got %q.", routeName, retName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubRouting(t *testing.T) {
|
||||
// Example from docs.
|
||||
router := NewRouter()
|
||||
subrouter := router.NewRoute().Host("www.example.com").Subrouter()
|
||||
route := subrouter.NewRoute().Path("/products/").Name("products")
|
||||
|
||||
url := "http://www.example.com/products/"
|
||||
request, _ := http.NewRequest("GET", url, nil)
|
||||
var rv RouteMatch
|
||||
ok := router.Match(request, &rv)
|
||||
|
||||
if !ok || rv.Route != route {
|
||||
t.Errorf("Expected same route, got %+v.", rv.Route)
|
||||
}
|
||||
|
||||
u, _ := router.Get("products").URL()
|
||||
builtURL := u.String()
|
||||
// Yay, subroute aware of the domain when building!
|
||||
if builtURL != url {
|
||||
t.Errorf("Expected %q, got %q.", url, builtURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVariableNames(t *testing.T) {
|
||||
route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
|
||||
if route.err == nil {
|
||||
t.Errorf("Expected error for duplicated variable names")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedirectSlash(t *testing.T) {
|
||||
var route *Route
|
||||
var routeMatch RouteMatch
|
||||
r := NewRouter()
|
||||
|
||||
r.StrictSlash(false)
|
||||
route = r.NewRoute()
|
||||
if route.strictSlash != false {
|
||||
t.Errorf("Expected false redirectSlash.")
|
||||
}
|
||||
|
||||
r.StrictSlash(true)
|
||||
route = r.NewRoute()
|
||||
if route.strictSlash != true {
|
||||
t.Errorf("Expected true redirectSlash.")
|
||||
}
|
||||
|
||||
route = new(Route)
|
||||
route.strictSlash = true
|
||||
route.Path("/{arg1}/{arg2:[0-9]+}/")
|
||||
request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
|
||||
routeMatch = RouteMatch{}
|
||||
_ = route.Match(request, &routeMatch)
|
||||
vars := routeMatch.Vars
|
||||
if vars["arg1"] != "foo" {
|
||||
t.Errorf("Expected foo.")
|
||||
}
|
||||
if vars["arg2"] != "123" {
|
||||
t.Errorf("Expected 123.")
|
||||
}
|
||||
rsp := NewRecorder()
|
||||
routeMatch.Handler.ServeHTTP(rsp, request)
|
||||
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
|
||||
t.Errorf("Expected redirect header.")
|
||||
}
|
||||
|
||||
route = new(Route)
|
||||
route.strictSlash = true
|
||||
route.Path("/{arg1}/{arg2:[0-9]+}")
|
||||
request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
|
||||
routeMatch = RouteMatch{}
|
||||
_ = route.Match(request, &routeMatch)
|
||||
vars = routeMatch.Vars
|
||||
if vars["arg1"] != "foo" {
|
||||
t.Errorf("Expected foo.")
|
||||
}
|
||||
if vars["arg2"] != "123" {
|
||||
t.Errorf("Expected 123.")
|
||||
}
|
||||
rsp = NewRecorder()
|
||||
routeMatch.Handler.ServeHTTP(rsp, request)
|
||||
if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
|
||||
t.Errorf("Expected redirect header.")
|
||||
}
|
||||
}
|
||||
|
||||
// Test for the new regexp library, still not available in stable Go.
|
||||
func TestNewRegexp(t *testing.T) {
|
||||
var p *routeRegexp
|
||||
var matches []string
|
||||
|
||||
tests := map[string]map[string][]string{
|
||||
"/{foo:a{2}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": nil,
|
||||
"/aaaa": nil,
|
||||
},
|
||||
"/{foo:a{2,}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": {"aaa"},
|
||||
"/aaaa": {"aaaa"},
|
||||
},
|
||||
"/{foo:a{2,3}}": {
|
||||
"/a": nil,
|
||||
"/aa": {"aa"},
|
||||
"/aaa": {"aaa"},
|
||||
"/aaaa": nil,
|
||||
},
|
||||
"/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
|
||||
"/a": nil,
|
||||
"/ab": nil,
|
||||
"/abc": nil,
|
||||
"/abcd": nil,
|
||||
"/abc/ab": {"abc", "ab"},
|
||||
"/abc/abc": nil,
|
||||
"/abcd/ab": nil,
|
||||
},
|
||||
`/{foo:\w{3,}}/{bar:\d{2,}}`: {
|
||||
"/a": nil,
|
||||
"/ab": nil,
|
||||
"/abc": nil,
|
||||
"/abc/1": nil,
|
||||
"/abc/12": {"abc", "12"},
|
||||
"/abcd/12": {"abcd", "12"},
|
||||
"/abcd/123": {"abcd", "123"},
|
||||
},
|
||||
}
|
||||
|
||||
for pattern, paths := range tests {
|
||||
p, _ = newRouteRegexp(pattern, false, false, false, false)
|
||||
for path, result := range paths {
|
||||
matches = p.regexp.FindStringSubmatch(path)
|
||||
if result == nil {
|
||||
if matches != nil {
|
||||
t.Errorf("%v should not match %v.", pattern, path)
|
||||
}
|
||||
} else {
|
||||
if len(matches) != len(result)+1 {
|
||||
t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
|
||||
} else {
|
||||
for k, v := range result {
|
||||
if matches[k+1] != v {
|
||||
t.Errorf("Expected %v, got %v.", v, matches[k+1])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/gorilla/websocket/bench_test.go
сгенерированный
поставляемый
Обычный файл
19
vendor/github.com/gorilla/websocket/bench_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,19 @@
|
||||
// Copyright 2014 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
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkMaskBytes(b *testing.B) {
|
||||
var key [4]byte
|
||||
data := make([]byte, 1024)
|
||||
pos := 0
|
||||
for i := 0; i < b.N; i++ {
|
||||
pos = maskBytes(key, pos, data)
|
||||
}
|
||||
b.SetBytes(int64(len(data)))
|
||||
}
|
||||
451
vendor/github.com/gorilla/websocket/client_server_test.go
сгенерированный
поставляемый
Обычный файл
451
vendor/github.com/gorilla/websocket/client_server_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,451 @@
|
||||
// Copyright 2013 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
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var cstUpgrader = Upgrader{
|
||||
Subprotocols: []string{"p0", "p1"},
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) {
|
||||
http.Error(w, reason.Error(), status)
|
||||
},
|
||||
}
|
||||
|
||||
var cstDialer = Dialer{
|
||||
Subprotocols: []string{"p1", "p2"},
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
type cstHandler struct{ *testing.T }
|
||||
|
||||
type cstServer struct {
|
||||
*httptest.Server
|
||||
URL string
|
||||
}
|
||||
|
||||
const (
|
||||
cstPath = "/a/b"
|
||||
cstRawQuery = "x=y"
|
||||
cstRequestURI = cstPath + "?" + cstRawQuery
|
||||
)
|
||||
|
||||
func newServer(t *testing.T) *cstServer {
|
||||
var s cstServer
|
||||
s.Server = httptest.NewServer(cstHandler{t})
|
||||
s.Server.URL += cstRequestURI
|
||||
s.URL = makeWsProto(s.Server.URL)
|
||||
return &s
|
||||
}
|
||||
|
||||
func newTLSServer(t *testing.T) *cstServer {
|
||||
var s cstServer
|
||||
s.Server = httptest.NewTLSServer(cstHandler{t})
|
||||
s.Server.URL += cstRequestURI
|
||||
s.URL = makeWsProto(s.Server.URL)
|
||||
return &s
|
||||
}
|
||||
|
||||
func (t cstHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != cstPath {
|
||||
t.Logf("path=%v, want %v", r.URL.Path, cstPath)
|
||||
http.Error(w, "bad path", 400)
|
||||
return
|
||||
}
|
||||
if r.URL.RawQuery != cstRawQuery {
|
||||
t.Logf("query=%v, want %v", r.URL.RawQuery, cstRawQuery)
|
||||
http.Error(w, "bad path", 400)
|
||||
return
|
||||
}
|
||||
subprotos := Subprotocols(r)
|
||||
if !reflect.DeepEqual(subprotos, cstDialer.Subprotocols) {
|
||||
t.Logf("subprotols=%v, want %v", subprotos, cstDialer.Subprotocols)
|
||||
http.Error(w, "bad protocol", 400)
|
||||
return
|
||||
}
|
||||
ws, err := cstUpgrader.Upgrade(w, r, http.Header{"Set-Cookie": {"sessionID=1234"}})
|
||||
if err != nil {
|
||||
t.Logf("Upgrade: %v", err)
|
||||
return
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
if ws.Subprotocol() != "p1" {
|
||||
t.Logf("Subprotocol() = %s, want p1", ws.Subprotocol())
|
||||
ws.Close()
|
||||
return
|
||||
}
|
||||
op, rd, err := ws.NextReader()
|
||||
if err != nil {
|
||||
t.Logf("NextReader: %v", err)
|
||||
return
|
||||
}
|
||||
wr, err := ws.NextWriter(op)
|
||||
if err != nil {
|
||||
t.Logf("NextWriter: %v", err)
|
||||
return
|
||||
}
|
||||
if _, err = io.Copy(wr, rd); err != nil {
|
||||
t.Logf("NextWriter: %v", err)
|
||||
return
|
||||
}
|
||||
if err := wr.Close(); err != nil {
|
||||
t.Logf("Close: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func makeWsProto(s string) string {
|
||||
return "ws" + strings.TrimPrefix(s, "http")
|
||||
}
|
||||
|
||||
func sendRecv(t *testing.T, ws *Conn) {
|
||||
const message = "Hello World!"
|
||||
if err := ws.SetWriteDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("SetWriteDeadline: %v", err)
|
||||
}
|
||||
if err := ws.WriteMessage(TextMessage, []byte(message)); err != nil {
|
||||
t.Fatalf("WriteMessage: %v", err)
|
||||
}
|
||||
if err := ws.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
|
||||
t.Fatalf("SetReadDeadline: %v", err)
|
||||
}
|
||||
_, p, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
t.Fatalf("ReadMessage: %v", err)
|
||||
}
|
||||
if string(p) != message {
|
||||
t.Fatalf("message=%s, want %s", p, message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyDial(t *testing.T) {
|
||||
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
surl, _ := url.Parse(s.URL)
|
||||
|
||||
cstDialer.Proxy = http.ProxyURL(surl)
|
||||
|
||||
connect := false
|
||||
origHandler := s.Server.Config.Handler
|
||||
|
||||
// Capture the request Host header.
|
||||
s.Server.Config.Handler = http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "CONNECT" {
|
||||
connect = true
|
||||
w.WriteHeader(200)
|
||||
return
|
||||
}
|
||||
|
||||
if !connect {
|
||||
t.Log("connect not recieved")
|
||||
http.Error(w, "connect not recieved", 405)
|
||||
return
|
||||
}
|
||||
origHandler.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
|
||||
cstDialer.Proxy = http.ProxyFromEnvironment
|
||||
}
|
||||
|
||||
func TestProxyAuthorizationDial(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
surl, _ := url.Parse(s.URL)
|
||||
surl.User = url.UserPassword("username", "password")
|
||||
cstDialer.Proxy = http.ProxyURL(surl)
|
||||
|
||||
connect := false
|
||||
origHandler := s.Server.Config.Handler
|
||||
|
||||
// Capture the request Host header.
|
||||
s.Server.Config.Handler = http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
proxyAuth := r.Header.Get("Proxy-Authorization")
|
||||
expectedProxyAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte("username:password"))
|
||||
if r.Method == "CONNECT" && proxyAuth == expectedProxyAuth {
|
||||
connect = true
|
||||
w.WriteHeader(200)
|
||||
return
|
||||
}
|
||||
|
||||
if !connect {
|
||||
t.Log("connect with proxy authorization not recieved")
|
||||
http.Error(w, "connect with proxy authorization not recieved", 405)
|
||||
return
|
||||
}
|
||||
origHandler.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
|
||||
cstDialer.Proxy = http.ProxyFromEnvironment
|
||||
}
|
||||
|
||||
func TestDial(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
|
||||
func TestDialTLS(t *testing.T) {
|
||||
s := newTLSServer(t)
|
||||
defer s.Close()
|
||||
|
||||
certs := x509.NewCertPool()
|
||||
for _, c := range s.TLS.Certificates {
|
||||
roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing server's root cert: %v", err)
|
||||
}
|
||||
for _, root := range roots {
|
||||
certs.AddCert(root)
|
||||
}
|
||||
}
|
||||
|
||||
u, _ := url.Parse(s.URL)
|
||||
d := cstDialer
|
||||
d.NetDial = func(network, addr string) (net.Conn, error) { return net.Dial(network, u.Host) }
|
||||
d.TLSClientConfig = &tls.Config{RootCAs: certs}
|
||||
ws, _, err := d.Dial("wss://example.com"+cstRequestURI, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
|
||||
func xTestDialTLSBadCert(t *testing.T) {
|
||||
// This test is deactivated because of noisy logging from the net/http package.
|
||||
s := newTLSServer(t)
|
||||
defer s.Close()
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Fatalf("Dial: nil")
|
||||
}
|
||||
}
|
||||
|
||||
func xTestDialTLSNoVerify(t *testing.T) {
|
||||
s := newTLSServer(t)
|
||||
defer s.Close()
|
||||
|
||||
d := cstDialer
|
||||
d.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
ws, _, err := d.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
|
||||
func TestDialTimeout(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
d := cstDialer
|
||||
d.HandshakeTimeout = -1
|
||||
ws, _, err := d.Dial(s.URL, nil)
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Fatalf("Dial: nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDialBadScheme(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.Server.URL, nil)
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Fatalf("Dial: nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDialBadOrigin(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Origin": {"bad"}})
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Fatalf("Dial: nil")
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatalf("resp=nil, err=%v", err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Fatalf("status=%d, want %d", resp.StatusCode, http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDialBadHeader(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
for _, k := range []string{"Upgrade",
|
||||
"Connection",
|
||||
"Sec-Websocket-Key",
|
||||
"Sec-Websocket-Version",
|
||||
"Sec-Websocket-Protocol"} {
|
||||
h := http.Header{}
|
||||
h.Set(k, "bad")
|
||||
ws, _, err := cstDialer.Dial(s.URL, http.Header{"Origin": {"bad"}})
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Errorf("Dial with header %s returned nil", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadMethod(t *testing.T) {
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := cstUpgrader.Upgrade(w, r, nil)
|
||||
if err == nil {
|
||||
t.Errorf("handshake succeeded, expect fail")
|
||||
ws.Close()
|
||||
}
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
resp, err := http.PostForm(s.URL, url.Values{})
|
||||
if err != nil {
|
||||
t.Fatalf("PostForm returned error %v", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusMethodNotAllowed {
|
||||
t.Errorf("Status = %d, want %d", resp.StatusCode, http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandshake(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
ws, resp, err := cstDialer.Dial(s.URL, http.Header{"Origin": {s.URL}})
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
var sessionID string
|
||||
for _, c := range resp.Cookies() {
|
||||
if c.Name == "sessionID" {
|
||||
sessionID = c.Value
|
||||
}
|
||||
}
|
||||
if sessionID != "1234" {
|
||||
t.Error("Set-Cookie not received from the server.")
|
||||
}
|
||||
|
||||
if ws.Subprotocol() != "p1" {
|
||||
t.Errorf("ws.Subprotocol() = %s, want p1", ws.Subprotocol())
|
||||
}
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
|
||||
func TestRespOnBadHandshake(t *testing.T) {
|
||||
const expectedStatus = http.StatusGone
|
||||
const expectedBody = "This is the response body."
|
||||
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(expectedStatus)
|
||||
io.WriteString(w, expectedBody)
|
||||
}))
|
||||
defer s.Close()
|
||||
|
||||
ws, resp, err := cstDialer.Dial(makeWsProto(s.URL), nil)
|
||||
if err == nil {
|
||||
ws.Close()
|
||||
t.Fatalf("Dial: nil")
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
t.Fatalf("resp=nil, err=%v", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != expectedStatus {
|
||||
t.Errorf("resp.StatusCode=%d, want %d", resp.StatusCode, expectedStatus)
|
||||
}
|
||||
|
||||
p, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFull(resp.Body) returned error %v", err)
|
||||
}
|
||||
|
||||
if string(p) != expectedBody {
|
||||
t.Errorf("resp.Body=%s, want %s", p, expectedBody)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHostHeader confirms that the host header provided in the call to Dial is
|
||||
// sent to the server.
|
||||
func TestHostHeader(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
specifiedHost := make(chan string, 1)
|
||||
origHandler := s.Server.Config.Handler
|
||||
|
||||
// Capture the request Host header.
|
||||
s.Server.Config.Handler = http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
specifiedHost <- r.Host
|
||||
origHandler.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, http.Header{"Host": {"testhost"}})
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
if gotHost := <-specifiedHost; gotHost != "testhost" {
|
||||
t.Fatalf("gotHost = %q, want \"testhost\"", gotHost)
|
||||
}
|
||||
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
72
vendor/github.com/gorilla/websocket/client_test.go
сгенерированный
поставляемый
Обычный файл
72
vendor/github.com/gorilla/websocket/client_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,72 @@
|
||||
// Copyright 2014 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
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var parseURLTests = []struct {
|
||||
s string
|
||||
u *url.URL
|
||||
rui string
|
||||
}{
|
||||
{"ws://example.com/", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
|
||||
{"ws://example.com", &url.URL{Scheme: "ws", Host: "example.com", Opaque: "/"}, "/"},
|
||||
{"ws://example.com:7777/", &url.URL{Scheme: "ws", Host: "example.com:7777", Opaque: "/"}, "/"},
|
||||
{"wss://example.com/", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/"}, "/"},
|
||||
{"wss://example.com/a/b", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b"}, "/a/b"},
|
||||
{"ss://example.com/a/b", nil, ""},
|
||||
{"ws://webmaster@example.com/", nil, ""},
|
||||
{"wss://example.com/a/b?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/a/b", RawQuery: "x=y"}, "/a/b?x=y"},
|
||||
{"wss://example.com?x=y", &url.URL{Scheme: "wss", Host: "example.com", Opaque: "/", RawQuery: "x=y"}, "/?x=y"},
|
||||
}
|
||||
|
||||
func TestParseURL(t *testing.T) {
|
||||
for _, tt := range parseURLTests {
|
||||
u, err := parseURL(tt.s)
|
||||
if tt.u != nil && err != nil {
|
||||
t.Errorf("parseURL(%q) returned error %v", tt.s, err)
|
||||
continue
|
||||
}
|
||||
if tt.u == nil {
|
||||
if err == nil {
|
||||
t.Errorf("parseURL(%q) did not return error", tt.s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(u, tt.u) {
|
||||
t.Errorf("parseURL(%q) = %v, want %v", tt.s, u, tt.u)
|
||||
continue
|
||||
}
|
||||
if u.RequestURI() != tt.rui {
|
||||
t.Errorf("parseURL(%q).RequestURI() = %v, want %v", tt.s, u.RequestURI(), tt.rui)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var hostPortNoPortTests = []struct {
|
||||
u *url.URL
|
||||
hostPort, hostNoPort string
|
||||
}{
|
||||
{&url.URL{Scheme: "ws", Host: "example.com"}, "example.com:80", "example.com"},
|
||||
{&url.URL{Scheme: "wss", Host: "example.com"}, "example.com:443", "example.com"},
|
||||
{&url.URL{Scheme: "ws", Host: "example.com:7777"}, "example.com:7777", "example.com"},
|
||||
{&url.URL{Scheme: "wss", Host: "example.com:7777"}, "example.com:7777", "example.com"},
|
||||
}
|
||||
|
||||
func TestHostPortNoPort(t *testing.T) {
|
||||
for _, tt := range hostPortNoPortTests {
|
||||
hostPort, hostNoPort := hostPortNoPort(tt.u)
|
||||
if hostPort != tt.hostPort {
|
||||
t.Errorf("hostPortNoPort(%v) returned hostPort %q, want %q", tt.u, hostPort, tt.hostPort)
|
||||
}
|
||||
if hostNoPort != tt.hostNoPort {
|
||||
t.Errorf("hostPortNoPort(%v) returned hostNoPort %q, want %q", tt.u, hostNoPort, tt.hostNoPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
402
vendor/github.com/gorilla/websocket/conn_test.go
сгенерированный
поставляемый
Обычный файл
402
vendor/github.com/gorilla/websocket/conn_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,402 @@
|
||||
// Copyright 2013 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
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ net.Error = errWriteTimeout
|
||||
|
||||
type fakeNetConn struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (c fakeNetConn) Close() error { return nil }
|
||||
func (c fakeNetConn) LocalAddr() net.Addr { return nil }
|
||||
func (c fakeNetConn) RemoteAddr() net.Addr { return nil }
|
||||
func (c fakeNetConn) SetDeadline(t time.Time) error { return nil }
|
||||
func (c fakeNetConn) SetReadDeadline(t time.Time) error { return nil }
|
||||
func (c fakeNetConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||
|
||||
func TestFraming(t *testing.T) {
|
||||
frameSizes := []int{0, 1, 2, 124, 125, 126, 127, 128, 129, 65534, 65535, 65536, 65537}
|
||||
var readChunkers = []struct {
|
||||
name string
|
||||
f func(io.Reader) io.Reader
|
||||
}{
|
||||
{"half", iotest.HalfReader},
|
||||
{"one", iotest.OneByteReader},
|
||||
{"asis", func(r io.Reader) io.Reader { return r }},
|
||||
}
|
||||
|
||||
writeBuf := make([]byte, 65537)
|
||||
for i := range writeBuf {
|
||||
writeBuf[i] = byte(i)
|
||||
}
|
||||
|
||||
for _, isServer := range []bool{true, false} {
|
||||
for _, chunker := range readChunkers {
|
||||
|
||||
var connBuf bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &connBuf}, isServer, 1024, 1024)
|
||||
rc := newConn(fakeNetConn{Reader: chunker.f(&connBuf), Writer: nil}, !isServer, 1024, 1024)
|
||||
|
||||
for _, n := range frameSizes {
|
||||
for _, iocopy := range []bool{true, false} {
|
||||
name := fmt.Sprintf("s:%v, r:%s, n:%d c:%v", isServer, chunker.name, n, iocopy)
|
||||
|
||||
w, err := wc.NextWriter(TextMessage)
|
||||
if err != nil {
|
||||
t.Errorf("%s: wc.NextWriter() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
var nn int
|
||||
if iocopy {
|
||||
var n64 int64
|
||||
n64, err = io.Copy(w, bytes.NewReader(writeBuf[:n]))
|
||||
nn = int(n64)
|
||||
} else {
|
||||
nn, err = w.Write(writeBuf[:n])
|
||||
}
|
||||
if err != nil || nn != n {
|
||||
t.Errorf("%s: w.Write(writeBuf[:n]) returned %d, %v", name, nn, err)
|
||||
continue
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
t.Errorf("%s: w.Close() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
opCode, r, err := rc.NextReader()
|
||||
if err != nil || opCode != TextMessage {
|
||||
t.Errorf("%s: NextReader() returned %d, r, %v", name, opCode, err)
|
||||
continue
|
||||
}
|
||||
rbuf, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("%s: ReadFull() returned rbuf, %v", name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(rbuf) != n {
|
||||
t.Errorf("%s: len(rbuf) is %d, want %d", name, len(rbuf), n)
|
||||
continue
|
||||
}
|
||||
|
||||
for i, b := range rbuf {
|
||||
if byte(i) != b {
|
||||
t.Errorf("%s: bad byte at offset %d", name, i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestControl(t *testing.T) {
|
||||
const message = "this is a ping/pong messsage"
|
||||
for _, isServer := range []bool{true, false} {
|
||||
for _, isWriteControl := range []bool{true, false} {
|
||||
name := fmt.Sprintf("s:%v, wc:%v", isServer, isWriteControl)
|
||||
var connBuf bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &connBuf}, isServer, 1024, 1024)
|
||||
rc := newConn(fakeNetConn{Reader: &connBuf, Writer: nil}, !isServer, 1024, 1024)
|
||||
if isWriteControl {
|
||||
wc.WriteControl(PongMessage, []byte(message), time.Now().Add(time.Second))
|
||||
} else {
|
||||
w, err := wc.NextWriter(PongMessage)
|
||||
if err != nil {
|
||||
t.Errorf("%s: wc.NextWriter() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
if _, err := w.Write([]byte(message)); err != nil {
|
||||
t.Errorf("%s: w.Write() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
t.Errorf("%s: w.Close() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
var actualMessage string
|
||||
rc.SetPongHandler(func(s string) error { actualMessage = s; return nil })
|
||||
rc.NextReader()
|
||||
if actualMessage != message {
|
||||
t.Errorf("%s: pong=%q, want %q", name, actualMessage, message)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloseBeforeFinalFrame(t *testing.T) {
|
||||
const bufSize = 512
|
||||
|
||||
expectedErr := &CloseError{Code: CloseNormalClosure, Text: "hello"}
|
||||
|
||||
var b1, b2 bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, bufSize)
|
||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
||||
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(make([]byte, bufSize+bufSize/2))
|
||||
wc.WriteControl(CloseMessage, FormatCloseMessage(expectedErr.Code, expectedErr.Text), time.Now().Add(10*time.Second))
|
||||
w.Close()
|
||||
|
||||
op, r, err := rc.NextReader()
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if !reflect.DeepEqual(err, expectedErr) {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, expectedErr)
|
||||
}
|
||||
_, _, err = rc.NextReader()
|
||||
if !reflect.DeepEqual(err, expectedErr) {
|
||||
t.Fatalf("NextReader() returned %v, want %v", err, expectedErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEOFWithinFrame(t *testing.T) {
|
||||
const bufSize = 64
|
||||
|
||||
for n := 0; ; n++ {
|
||||
var b bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b}, false, 1024, 1024)
|
||||
rc := newConn(fakeNetConn{Reader: &b, Writer: nil}, true, 1024, 1024)
|
||||
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(make([]byte, bufSize))
|
||||
w.Close()
|
||||
|
||||
if n >= b.Len() {
|
||||
break
|
||||
}
|
||||
b.Truncate(n)
|
||||
|
||||
op, r, err := rc.NextReader()
|
||||
if err == errUnexpectedEOF {
|
||||
continue
|
||||
}
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("%d: NextReader() returned %d, %v", n, op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("%d: io.Copy() returned %v, want %v", n, err, errUnexpectedEOF)
|
||||
}
|
||||
_, _, err = rc.NextReader()
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("%d: NextReader() returned %v, want %v", n, err, errUnexpectedEOF)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEOFBeforeFinalFrame(t *testing.T) {
|
||||
const bufSize = 512
|
||||
|
||||
var b1, b2 bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, bufSize)
|
||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
||||
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(make([]byte, bufSize+bufSize/2))
|
||||
|
||||
op, r, err := rc.NextReader()
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("io.Copy() returned %v, want %v", err, errUnexpectedEOF)
|
||||
}
|
||||
_, _, err = rc.NextReader()
|
||||
if err != errUnexpectedEOF {
|
||||
t.Fatalf("NextReader() returned %v, want %v", err, errUnexpectedEOF)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadLimit(t *testing.T) {
|
||||
|
||||
const readLimit = 512
|
||||
message := make([]byte, readLimit+1)
|
||||
|
||||
var b1, b2 bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, 1024, readLimit-2)
|
||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, 1024, 1024)
|
||||
rc.SetReadLimit(readLimit)
|
||||
|
||||
// Send message at the limit with interleaved pong.
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(message[:readLimit-1])
|
||||
wc.WriteControl(PongMessage, []byte("this is a pong"), time.Now().Add(10*time.Second))
|
||||
w.Write(message[:1])
|
||||
w.Close()
|
||||
|
||||
// Send message larger than the limit.
|
||||
wc.WriteMessage(BinaryMessage, message[:readLimit+1])
|
||||
|
||||
op, _, err := rc.NextReader()
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("1: NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
op, r, err := rc.NextReader()
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("2: NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
_, err = io.Copy(ioutil.Discard, r)
|
||||
if err != ErrReadLimit {
|
||||
t.Fatalf("io.Copy() returned %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnderlyingConn(t *testing.T) {
|
||||
var b1, b2 bytes.Buffer
|
||||
fc := fakeNetConn{Reader: &b1, Writer: &b2}
|
||||
c := newConn(fc, true, 1024, 1024)
|
||||
ul := c.UnderlyingConn()
|
||||
if ul != fc {
|
||||
t.Fatalf("Underlying conn is not what it should be.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBufioReadBytes(t *testing.T) {
|
||||
|
||||
// Test calling bufio.ReadBytes for value longer than read buffer size.
|
||||
|
||||
m := make([]byte, 512)
|
||||
m[len(m)-1] = '\n'
|
||||
|
||||
var b1, b2 bytes.Buffer
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &b1}, false, len(m)+64, len(m)+64)
|
||||
rc := newConn(fakeNetConn{Reader: &b1, Writer: &b2}, true, len(m)-64, len(m)-64)
|
||||
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
w.Write(m)
|
||||
w.Close()
|
||||
|
||||
op, r, err := rc.NextReader()
|
||||
if op != BinaryMessage || err != nil {
|
||||
t.Fatalf("NextReader() returned %d, %v", op, err)
|
||||
}
|
||||
|
||||
br := bufio.NewReader(r)
|
||||
p, err := br.ReadBytes('\n')
|
||||
if err != nil {
|
||||
t.Fatalf("ReadBytes() returned %v", err)
|
||||
}
|
||||
if len(p) != len(m) {
|
||||
t.Fatalf("read returnd %d bytes, want %d bytes", len(p), len(m))
|
||||
}
|
||||
}
|
||||
|
||||
var closeErrorTests = []struct {
|
||||
err error
|
||||
codes []int
|
||||
ok bool
|
||||
}{
|
||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNormalClosure}, true},
|
||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived}, false},
|
||||
{&CloseError{Code: CloseNormalClosure}, []int{CloseNoStatusReceived, CloseNormalClosure}, true},
|
||||
{errors.New("hello"), []int{CloseNormalClosure}, false},
|
||||
}
|
||||
|
||||
func TestCloseError(t *testing.T) {
|
||||
for _, tt := range closeErrorTests {
|
||||
ok := IsCloseError(tt.err, tt.codes...)
|
||||
if ok != tt.ok {
|
||||
t.Errorf("IsCloseError(%#v, %#v) returned %v, want %v", tt.err, tt.codes, ok, tt.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type blockingWriter struct {
|
||||
c1, c2 chan struct{}
|
||||
}
|
||||
|
||||
func (w blockingWriter) Write(p []byte) (int, error) {
|
||||
// Allow main to continue
|
||||
close(w.c1)
|
||||
// Wait for panic in main
|
||||
<-w.c2
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func TestConcurrentWritePanic(t *testing.T) {
|
||||
w := blockingWriter{make(chan struct{}), make(chan struct{})}
|
||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
||||
go func() {
|
||||
c.WriteMessage(TextMessage, []byte{})
|
||||
}()
|
||||
|
||||
// wait for goroutine to block in write.
|
||||
<-w.c1
|
||||
|
||||
defer func() {
|
||||
close(w.c2)
|
||||
if v := recover(); v != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
c.WriteMessage(TextMessage, []byte{})
|
||||
t.Fatal("should not get here")
|
||||
}
|
||||
|
||||
type failingReader struct{}
|
||||
|
||||
func (r failingReader) Read(p []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func TestFailedConnectionReadPanic(t *testing.T) {
|
||||
c := newConn(fakeNetConn{Reader: failingReader{}, Writer: nil}, false, 1024, 1024)
|
||||
|
||||
defer func() {
|
||||
if v := recover(); v != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
for i := 0; i < 20000; i++ {
|
||||
c.ReadMessage()
|
||||
}
|
||||
t.Fatal("should not get here")
|
||||
}
|
||||
46
vendor/github.com/gorilla/websocket/example_test.go
сгенерированный
поставляемый
Обычный файл
46
vendor/github.com/gorilla/websocket/example_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,46 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
var (
|
||||
c *websocket.Conn
|
||||
req *http.Request
|
||||
)
|
||||
|
||||
// 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() {
|
||||
|
||||
for {
|
||||
messageType, p, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
||||
log.Printf("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) {}
|
||||
13
vendor/github.com/gorilla/websocket/examples/autobahn/README.md
сгенерированный
поставляемый
Обычный файл
13
vendor/github.com/gorilla/websocket/examples/autobahn/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
||||
# Test Server
|
||||
|
||||
This package contains a server for the [Autobahn WebSockets Test Suite](http://autobahn.ws/testsuite).
|
||||
|
||||
To test the server, run
|
||||
|
||||
go run server.go
|
||||
|
||||
and start the client test driver
|
||||
|
||||
wstest -m fuzzingclient -s fuzzingclient.json
|
||||
|
||||
When the client completes, it writes a report to reports/clients/index.html.
|
||||
14
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
сгенерированный
поставляемый
Обычный файл
14
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,14 @@
|
||||
|
||||
{
|
||||
"options": {"failByDrop": false},
|
||||
"outdir": "./reports/clients",
|
||||
"servers": [
|
||||
{"agent": "ReadAllWriteMessage", "url": "ws://localhost:9000/m", "options": {"version": 18}},
|
||||
{"agent": "ReadAllWrite", "url": "ws://localhost:9000/r", "options": {"version": 18}},
|
||||
{"agent": "CopyFull", "url": "ws://localhost:9000/f", "options": {"version": 18}},
|
||||
{"agent": "CopyWriterOnly", "url": "ws://localhost:9000/c", "options": {"version": 18}}
|
||||
],
|
||||
"cases": ["*"],
|
||||
"exclude-cases": [],
|
||||
"exclude-agent-cases": {}
|
||||
}
|
||||
246
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
сгенерированный
поставляемый
Обычный файл
246
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,246 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Command server is a test server for the Autobahn WebSockets Test Suite.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"github.com/gorilla/websocket"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 4096,
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
// echoCopy echoes messages from the client using io.Copy.
|
||||
func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println("Upgrade:", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
for {
|
||||
mt, r, err := conn.NextReader()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Println("NextReader:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if mt == websocket.TextMessage {
|
||||
r = &validator{r: r}
|
||||
}
|
||||
w, err := conn.NextWriter(mt)
|
||||
if err != nil {
|
||||
log.Println("NextWriter:", err)
|
||||
return
|
||||
}
|
||||
if mt == websocket.TextMessage {
|
||||
r = &validator{r: r}
|
||||
}
|
||||
if writerOnly {
|
||||
_, err = io.Copy(struct{ io.Writer }{w}, r)
|
||||
} else {
|
||||
_, err = io.Copy(w, r)
|
||||
}
|
||||
if err != nil {
|
||||
if err == errInvalidUTF8 {
|
||||
conn.WriteControl(websocket.CloseMessage,
|
||||
websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
|
||||
time.Time{})
|
||||
}
|
||||
log.Println("Copy:", err)
|
||||
return
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
log.Println("Close:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func echoCopyWriterOnly(w http.ResponseWriter, r *http.Request) {
|
||||
echoCopy(w, r, true)
|
||||
}
|
||||
|
||||
func echoCopyFull(w http.ResponseWriter, r *http.Request) {
|
||||
echoCopy(w, r, false)
|
||||
}
|
||||
|
||||
// echoReadAll echoes messages from the client by reading the entire message
|
||||
// with ioutil.ReadAll.
|
||||
func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println("Upgrade:", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
for {
|
||||
mt, b, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Println("NextReader:", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if mt == websocket.TextMessage {
|
||||
if !utf8.Valid(b) {
|
||||
conn.WriteControl(websocket.CloseMessage,
|
||||
websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
|
||||
time.Time{})
|
||||
log.Println("ReadAll: invalid utf8")
|
||||
}
|
||||
}
|
||||
if writeMessage {
|
||||
err = conn.WriteMessage(mt, b)
|
||||
if err != nil {
|
||||
log.Println("WriteMessage:", err)
|
||||
}
|
||||
} else {
|
||||
w, err := conn.NextWriter(mt)
|
||||
if err != nil {
|
||||
log.Println("NextWriter:", err)
|
||||
return
|
||||
}
|
||||
if _, err := w.Write(b); err != nil {
|
||||
log.Println("Writer:", err)
|
||||
return
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
log.Println("Close:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func echoReadAllWriter(w http.ResponseWriter, r *http.Request) {
|
||||
echoReadAll(w, r, false)
|
||||
}
|
||||
|
||||
func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
|
||||
echoReadAll(w, r, true)
|
||||
}
|
||||
|
||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.Error(w, "Not found.", 404)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
io.WriteString(w, "<html><body>Echo Server</body></html>")
|
||||
}
|
||||
|
||||
var addr = flag.String("addr", ":9000", "http service address")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
http.HandleFunc("/", serveHome)
|
||||
http.HandleFunc("/c", echoCopyWriterOnly)
|
||||
http.HandleFunc("/f", echoCopyFull)
|
||||
http.HandleFunc("/r", echoReadAllWriter)
|
||||
http.HandleFunc("/m", echoReadAllWriteMessage)
|
||||
err := http.ListenAndServe(*addr, nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
type validator struct {
|
||||
state int
|
||||
x rune
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
var errInvalidUTF8 = errors.New("invalid utf8")
|
||||
|
||||
func (r *validator) Read(p []byte) (int, error) {
|
||||
n, err := r.r.Read(p)
|
||||
state := r.state
|
||||
x := r.x
|
||||
for _, b := range p[:n] {
|
||||
state, x = decode(state, x, b)
|
||||
if state == utf8Reject {
|
||||
break
|
||||
}
|
||||
}
|
||||
r.state = state
|
||||
r.x = x
|
||||
if state == utf8Reject || (err == io.EOF && state != utf8Accept) {
|
||||
return n, errInvalidUTF8
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// UTF-8 decoder from http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
//
|
||||
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
var utf8d = [...]byte{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7f
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9f
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // a0..bf
|
||||
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c0..df
|
||||
0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // e0..ef
|
||||
0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // f0..ff
|
||||
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
|
||||
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
|
||||
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
|
||||
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // s7..s8
|
||||
}
|
||||
|
||||
const (
|
||||
utf8Accept = 0
|
||||
utf8Reject = 1
|
||||
)
|
||||
|
||||
func decode(state int, x rune, b byte) (int, rune) {
|
||||
t := utf8d[b]
|
||||
if state != utf8Accept {
|
||||
x = rune(b&0x3f) | (x << 6)
|
||||
} else {
|
||||
x = rune((0xff >> t) & b)
|
||||
}
|
||||
state = int(utf8d[256+state*16+int(t)])
|
||||
return state, x
|
||||
}
|
||||
20
vendor/github.com/gorilla/websocket/examples/chat/README.md
сгенерированный
поставляемый
Обычный файл
20
vendor/github.com/gorilla/websocket/examples/chat/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,20 @@
|
||||
# Chat Example
|
||||
|
||||
This application shows how to use use the
|
||||
[websocket](https://github.com/gorilla/websocket) package and
|
||||
[jQuery](http://jquery.com) to implement a simple web chat application.
|
||||
|
||||
## Running the example
|
||||
|
||||
The example requires a working Go development environment. The [Getting
|
||||
Started](http://golang.org/doc/install) page describes how to install the
|
||||
development environment.
|
||||
|
||||
Once you have Go up and running, you can download, build and run the example
|
||||
using the following commands.
|
||||
|
||||
$ go get github.com/gorilla/websocket
|
||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/chat`
|
||||
$ go run *.go
|
||||
|
||||
To use the chat example, open http://localhost:8080/ in your browser.
|
||||
105
vendor/github.com/gorilla/websocket/examples/chat/conn.go
сгенерированный
поставляемый
Обычный файл
105
vendor/github.com/gorilla/websocket/examples/chat/conn.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,105 @@
|
||||
// Copyright 2013 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 main
|
||||
|
||||
import (
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Time allowed to write a message to the peer.
|
||||
writeWait = 10 * time.Second
|
||||
|
||||
// Time allowed to read the next pong message from the peer.
|
||||
pongWait = 60 * time.Second
|
||||
|
||||
// Send pings to peer with this period. Must be less than pongWait.
|
||||
pingPeriod = (pongWait * 9) / 10
|
||||
|
||||
// Maximum message size allowed from peer.
|
||||
maxMessageSize = 512
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
// connection is an middleman between the websocket connection and the hub.
|
||||
type connection struct {
|
||||
// The websocket connection.
|
||||
ws *websocket.Conn
|
||||
|
||||
// Buffered channel of outbound messages.
|
||||
send chan []byte
|
||||
}
|
||||
|
||||
// readPump pumps messages from the websocket connection to the hub.
|
||||
func (c *connection) readPump() {
|
||||
defer func() {
|
||||
h.unregister <- c
|
||||
c.ws.Close()
|
||||
}()
|
||||
c.ws.SetReadLimit(maxMessageSize)
|
||||
c.ws.SetReadDeadline(time.Now().Add(pongWait))
|
||||
c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
for {
|
||||
_, message, err := c.ws.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
|
||||
log.Printf("error: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
h.broadcast <- message
|
||||
}
|
||||
}
|
||||
|
||||
// write writes a message with the given message type and payload.
|
||||
func (c *connection) write(mt int, payload []byte) error {
|
||||
c.ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
return c.ws.WriteMessage(mt, payload)
|
||||
}
|
||||
|
||||
// writePump pumps messages from the hub to the websocket connection.
|
||||
func (c *connection) writePump() {
|
||||
ticker := time.NewTicker(pingPeriod)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
c.ws.Close()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case message, ok := <-c.send:
|
||||
if !ok {
|
||||
c.write(websocket.CloseMessage, []byte{})
|
||||
return
|
||||
}
|
||||
if err := c.write(websocket.TextMessage, message); err != nil {
|
||||
return
|
||||
}
|
||||
case <-ticker.C:
|
||||
if err := c.write(websocket.PingMessage, []byte{}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// serveWs handles websocket requests from the peer.
|
||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
c := &connection{send: make(chan []byte, 256), ws: ws}
|
||||
h.register <- c
|
||||
go c.writePump()
|
||||
c.readPump()
|
||||
}
|
||||
92
vendor/github.com/gorilla/websocket/examples/chat/home.html
сгенерированный
поставляемый
Обычный файл
92
vendor/github.com/gorilla/websocket/examples/chat/home.html
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Chat Example</title>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
||||
var conn;
|
||||
var msg = $("#msg");
|
||||
var log = $("#log");
|
||||
|
||||
function appendLog(msg) {
|
||||
var d = log[0]
|
||||
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
|
||||
msg.appendTo(log)
|
||||
if (doScroll) {
|
||||
d.scrollTop = d.scrollHeight - d.clientHeight;
|
||||
}
|
||||
}
|
||||
|
||||
$("#form").submit(function() {
|
||||
if (!conn) {
|
||||
return false;
|
||||
}
|
||||
if (!msg.val()) {
|
||||
return false;
|
||||
}
|
||||
conn.send(msg.val());
|
||||
msg.val("");
|
||||
return false
|
||||
});
|
||||
|
||||
if (window["WebSocket"]) {
|
||||
conn = new WebSocket("ws://{{$}}/ws");
|
||||
conn.onclose = function(evt) {
|
||||
appendLog($("<div><b>Connection closed.</b></div>"))
|
||||
}
|
||||
conn.onmessage = function(evt) {
|
||||
appendLog($("<div/>").text(evt.data))
|
||||
}
|
||||
} else {
|
||||
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
html {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: gray;
|
||||
}
|
||||
|
||||
#log {
|
||||
background: white;
|
||||
margin: 0;
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
position: absolute;
|
||||
top: 0.5em;
|
||||
left: 0.5em;
|
||||
right: 0.5em;
|
||||
bottom: 3em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#form {
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 1em;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<form id="form">
|
||||
<input type="submit" value="Send" />
|
||||
<input type="text" id="msg" size="64"/>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
51
vendor/github.com/gorilla/websocket/examples/chat/hub.go
сгенерированный
поставляемый
Обычный файл
51
vendor/github.com/gorilla/websocket/examples/chat/hub.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,51 @@
|
||||
// Copyright 2013 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 main
|
||||
|
||||
// hub maintains the set of active connections and broadcasts messages to the
|
||||
// connections.
|
||||
type hub struct {
|
||||
// Registered connections.
|
||||
connections map[*connection]bool
|
||||
|
||||
// Inbound messages from the connections.
|
||||
broadcast chan []byte
|
||||
|
||||
// Register requests from the connections.
|
||||
register chan *connection
|
||||
|
||||
// Unregister requests from connections.
|
||||
unregister chan *connection
|
||||
}
|
||||
|
||||
var h = hub{
|
||||
broadcast: make(chan []byte),
|
||||
register: make(chan *connection),
|
||||
unregister: make(chan *connection),
|
||||
connections: make(map[*connection]bool),
|
||||
}
|
||||
|
||||
func (h *hub) run() {
|
||||
for {
|
||||
select {
|
||||
case c := <-h.register:
|
||||
h.connections[c] = true
|
||||
case c := <-h.unregister:
|
||||
if _, ok := h.connections[c]; ok {
|
||||
delete(h.connections, c)
|
||||
close(c.send)
|
||||
}
|
||||
case m := <-h.broadcast:
|
||||
for c := range h.connections {
|
||||
select {
|
||||
case c.send <- m:
|
||||
default:
|
||||
close(c.send)
|
||||
delete(h.connections, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
vendor/github.com/gorilla/websocket/examples/chat/main.go
сгенерированный
поставляемый
Обычный файл
39
vendor/github.com/gorilla/websocket/examples/chat/main.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,39 @@
|
||||
// Copyright 2013 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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", ":8080", "http service address")
|
||||
var homeTempl = template.Must(template.ParseFiles("home.html"))
|
||||
|
||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.Error(w, "Not found", 404)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
homeTempl.Execute(w, r.Host)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
go h.run()
|
||||
http.HandleFunc("/", serveHome)
|
||||
http.HandleFunc("/ws", serveWs)
|
||||
err := http.ListenAndServe(*addr, nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/gorilla/websocket/examples/command/README.md
сгенерированный
поставляемый
Обычный файл
19
vendor/github.com/gorilla/websocket/examples/command/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,19 @@
|
||||
# Command example
|
||||
|
||||
This example connects a websocket connection to stdin and stdout of a command.
|
||||
Received messages are written to stdin followed by a `\n`. Each line read from
|
||||
from standard out is sent as a message to the client.
|
||||
|
||||
$ go get github.com/gorilla/websocket
|
||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/command`
|
||||
$ go run main.go <command and arguments to run>
|
||||
# Open http://localhost:8080/ .
|
||||
|
||||
Try the following commands.
|
||||
|
||||
# Echo sent messages to the output area.
|
||||
$ go run main.go cat
|
||||
|
||||
# Run a shell.Try sending "ls" and "cat main.go".
|
||||
$ go run main.go sh
|
||||
|
||||
96
vendor/github.com/gorilla/websocket/examples/command/home.html
сгенерированный
поставляемый
Обычный файл
96
vendor/github.com/gorilla/websocket/examples/command/home.html
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Command Example</title>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
|
||||
var conn;
|
||||
var msg = $("#msg");
|
||||
var log = $("#log");
|
||||
|
||||
function appendLog(msg) {
|
||||
var d = log[0]
|
||||
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
|
||||
msg.appendTo(log)
|
||||
if (doScroll) {
|
||||
d.scrollTop = d.scrollHeight - d.clientHeight;
|
||||
}
|
||||
}
|
||||
|
||||
$("#form").submit(function() {
|
||||
if (!conn) {
|
||||
return false;
|
||||
}
|
||||
if (!msg.val()) {
|
||||
return false;
|
||||
}
|
||||
conn.send(msg.val());
|
||||
msg.val("");
|
||||
return false
|
||||
});
|
||||
|
||||
if (window["WebSocket"]) {
|
||||
conn = new WebSocket("ws://{{$}}/ws");
|
||||
conn.onclose = function(evt) {
|
||||
appendLog($("<div><b>Connection closed.</b></div>"))
|
||||
}
|
||||
conn.onmessage = function(evt) {
|
||||
appendLog($("<pre/>").text(evt.data))
|
||||
}
|
||||
} else {
|
||||
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
html {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: gray;
|
||||
}
|
||||
|
||||
#log {
|
||||
background: white;
|
||||
margin: 0;
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
position: absolute;
|
||||
top: 0.5em;
|
||||
left: 0.5em;
|
||||
right: 0.5em;
|
||||
bottom: 3em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#log pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#form {
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
bottom: 1em;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<form id="form">
|
||||
<input type="submit" value="Send" />
|
||||
<input type="text" id="msg" size="64"/>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
188
vendor/github.com/gorilla/websocket/examples/command/main.go
сгенерированный
поставляемый
Обычный файл
188
vendor/github.com/gorilla/websocket/examples/command/main.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,188 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("addr", "127.0.0.1:8080", "http service address")
|
||||
cmdPath string
|
||||
homeTempl = template.Must(template.ParseFiles("home.html"))
|
||||
)
|
||||
|
||||
const (
|
||||
// Time allowed to write a message to the peer.
|
||||
writeWait = 10 * time.Second
|
||||
|
||||
// Maximum message size allowed from peer.
|
||||
maxMessageSize = 8192
|
||||
|
||||
// Time allowed to read the next pong message from the peer.
|
||||
pongWait = 60 * time.Second
|
||||
|
||||
// Send pings to peer with this period. Must be less than pongWait.
|
||||
pingPeriod = (pongWait * 9) / 10
|
||||
)
|
||||
|
||||
func pumpStdin(ws *websocket.Conn, w io.Writer) {
|
||||
defer ws.Close()
|
||||
ws.SetReadLimit(maxMessageSize)
|
||||
ws.SetReadDeadline(time.Now().Add(pongWait))
|
||||
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
for {
|
||||
_, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
message = append(message, '\n')
|
||||
if _, err := w.Write(message); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pumpStdout(ws *websocket.Conn, r io.Reader, done chan struct{}) {
|
||||
defer func() {
|
||||
ws.Close()
|
||||
close(done)
|
||||
}()
|
||||
s := bufio.NewScanner(r)
|
||||
for s.Scan() {
|
||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if s.Err() != nil {
|
||||
log.Println("scan:", s.Err())
|
||||
}
|
||||
}
|
||||
|
||||
func ping(ws *websocket.Conn, done chan struct{}) {
|
||||
ticker := time.NewTicker(pingPeriod)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
|
||||
log.Println("ping:", err)
|
||||
}
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func internalError(ws *websocket.Conn, msg string, err error) {
|
||||
log.Println(msg, err)
|
||||
ws.WriteMessage(websocket.TextMessage, []byte("Internal server error."))
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{}
|
||||
|
||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println("upgrade:", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer ws.Close()
|
||||
|
||||
outr, outw, err := os.Pipe()
|
||||
if err != nil {
|
||||
internalError(ws, "stdout:", err)
|
||||
return
|
||||
}
|
||||
defer outr.Close()
|
||||
defer outw.Close()
|
||||
|
||||
inr, inw, err := os.Pipe()
|
||||
if err != nil {
|
||||
internalError(ws, "stdin:", err)
|
||||
return
|
||||
}
|
||||
defer inr.Close()
|
||||
defer inw.Close()
|
||||
|
||||
proc, err := os.StartProcess(cmdPath, flag.Args(), &os.ProcAttr{
|
||||
Files: []*os.File{inr, outw, outw},
|
||||
})
|
||||
if err != nil {
|
||||
internalError(ws, "start:", err)
|
||||
return
|
||||
}
|
||||
|
||||
inr.Close()
|
||||
outw.Close()
|
||||
|
||||
stdoutDone := make(chan struct{})
|
||||
go pumpStdout(ws, outr, stdoutDone)
|
||||
go ping(ws, stdoutDone)
|
||||
|
||||
pumpStdin(ws, inw)
|
||||
|
||||
// Some commands will exit when stdin is closed.
|
||||
inw.Close()
|
||||
|
||||
// Other commands need a bonk on the head.
|
||||
if err := proc.Signal(os.Interrupt); err != nil {
|
||||
log.Println("inter:", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-stdoutDone:
|
||||
case <-time.After(time.Second):
|
||||
// A bigger bonk on the head.
|
||||
if err := proc.Signal(os.Kill); err != nil {
|
||||
log.Println("term:", err)
|
||||
}
|
||||
<-stdoutDone
|
||||
}
|
||||
|
||||
if _, err := proc.Wait(); err != nil {
|
||||
log.Println("wait:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.Error(w, "Not found", 404)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
homeTempl.Execute(w, r.Host)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if len(flag.Args()) < 1 {
|
||||
log.Fatal("must specify at least one argument")
|
||||
}
|
||||
var err error
|
||||
cmdPath, err = exec.LookPath(flag.Args()[0])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
http.HandleFunc("/", serveHome)
|
||||
http.HandleFunc("/ws", serveWs)
|
||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
||||
}
|
||||
17
vendor/github.com/gorilla/websocket/examples/echo/README.md
сгенерированный
поставляемый
Обычный файл
17
vendor/github.com/gorilla/websocket/examples/echo/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,17 @@
|
||||
# Client and server example
|
||||
|
||||
This example shows a simple client and server.
|
||||
|
||||
The server echoes messages sent to it. The client sends a message every second
|
||||
and prints all messages received.
|
||||
|
||||
To run the example, start the server:
|
||||
|
||||
$ go run server.go
|
||||
|
||||
Next, start the client:
|
||||
|
||||
$ go run client.go
|
||||
|
||||
The server includes a simple web client. To use the client, open
|
||||
http://127.0.0.1:8080 in the browser and follow the instructions on the page.
|
||||
81
vendor/github.com/gorilla/websocket/examples/echo/client.go
сгенерированный
поставляемый
Обычный файл
81
vendor/github.com/gorilla/websocket/examples/echo/client.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,81 @@
|
||||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", "localhost:8080", "http service address")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
|
||||
u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
|
||||
log.Printf("connecting to %s", u.String())
|
||||
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
if err != nil {
|
||||
log.Fatal("dial:", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
defer c.Close()
|
||||
defer close(done)
|
||||
for {
|
||||
_, message, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("read:", err)
|
||||
return
|
||||
}
|
||||
log.Printf("recv: %s", message)
|
||||
}
|
||||
}()
|
||||
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case t := <-ticker.C:
|
||||
err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
|
||||
if err != nil {
|
||||
log.Println("write:", err)
|
||||
return
|
||||
}
|
||||
case <-interrupt:
|
||||
log.Println("interrupt")
|
||||
// To cleanly close a connection, a client should send a close
|
||||
// frame and wait for the server to close the connection.
|
||||
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
if err != nil {
|
||||
log.Println("write close:", err)
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(time.Second):
|
||||
}
|
||||
c.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
132
vendor/github.com/gorilla/websocket/examples/echo/server.go
сгенерированный
поставляемый
Обычный файл
132
vendor/github.com/gorilla/websocket/examples/echo/server.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,132 @@
|
||||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", "localhost:8080", "http service address")
|
||||
|
||||
var upgrader = websocket.Upgrader{} // use default options
|
||||
|
||||
func echo(w http.ResponseWriter, r *http.Request) {
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Print("upgrade:", err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
for {
|
||||
mt, message, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("read:", err)
|
||||
break
|
||||
}
|
||||
log.Printf("recv: %s", message)
|
||||
err = c.WriteMessage(mt, message)
|
||||
if err != nil {
|
||||
log.Println("write:", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func home(w http.ResponseWriter, r *http.Request) {
|
||||
homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
http.HandleFunc("/echo", echo)
|
||||
http.HandleFunc("/", home)
|
||||
log.Fatal(http.ListenAndServe(*addr, nil))
|
||||
}
|
||||
|
||||
var homeTemplate = template.Must(template.New("").Parse(`
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
window.addEventListener("load", function(evt) {
|
||||
|
||||
var output = document.getElementById("output");
|
||||
var input = document.getElementById("input");
|
||||
var ws;
|
||||
|
||||
var print = function(message) {
|
||||
var d = document.createElement("div");
|
||||
d.innerHTML = message;
|
||||
output.appendChild(d);
|
||||
};
|
||||
|
||||
document.getElementById("open").onclick = function(evt) {
|
||||
if (ws) {
|
||||
return false;
|
||||
}
|
||||
ws = new WebSocket("{{.}}");
|
||||
ws.onopen = function(evt) {
|
||||
print("OPEN");
|
||||
}
|
||||
ws.onclose = function(evt) {
|
||||
print("CLOSE");
|
||||
ws = null;
|
||||
}
|
||||
ws.onmessage = function(evt) {
|
||||
print("RESPONSE: " + evt.data);
|
||||
}
|
||||
ws.onerror = function(evt) {
|
||||
print("ERROR: " + evt.data);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
document.getElementById("send").onclick = function(evt) {
|
||||
if (!ws) {
|
||||
return false;
|
||||
}
|
||||
print("SEND: " + input.value);
|
||||
ws.send(input.value);
|
||||
return false;
|
||||
};
|
||||
|
||||
document.getElementById("close").onclick = function(evt) {
|
||||
if (!ws) {
|
||||
return false;
|
||||
}
|
||||
ws.close();
|
||||
return false;
|
||||
};
|
||||
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td valign="top" width="50%">
|
||||
<p>Click "Open" to create a connection to the server,
|
||||
"Send" to send a message to the server and "Close" to close the connection.
|
||||
You can change the message and send multiple times.
|
||||
<p>
|
||||
<form>
|
||||
<button id="open">Open</button>
|
||||
<button id="close">Close</button>
|
||||
<p><input id="input" type="text" value="Hello world!">
|
||||
<button id="send">Send</button>
|
||||
</form>
|
||||
</td><td valign="top" width="50%">
|
||||
<div id="output"></div>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
9
vendor/github.com/gorilla/websocket/examples/filewatch/README.md
сгенерированный
поставляемый
Обычный файл
9
vendor/github.com/gorilla/websocket/examples/filewatch/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,9 @@
|
||||
# File Watch example.
|
||||
|
||||
This example sends a file to the browser client for display whenever the file is modified.
|
||||
|
||||
$ go get github.com/gorilla/websocket
|
||||
$ cd `go list -f '{{.Dir}}' github.com/gorilla/websocket/examples/filewatch`
|
||||
$ go run main.go <name of file to watch>
|
||||
# Open http://localhost:8080/ .
|
||||
# Modify the file to see it update in the browser.
|
||||
193
vendor/github.com/gorilla/websocket/examples/filewatch/main.go
сгенерированный
поставляемый
Обычный файл
193
vendor/github.com/gorilla/websocket/examples/filewatch/main.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,193 @@
|
||||
// Copyright 2013 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 main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
// Time allowed to write the file to the client.
|
||||
writeWait = 10 * time.Second
|
||||
|
||||
// Time allowed to read the next pong message from the client.
|
||||
pongWait = 60 * time.Second
|
||||
|
||||
// Send pings to client with this period. Must be less than pongWait.
|
||||
pingPeriod = (pongWait * 9) / 10
|
||||
|
||||
// Poll file for changes with this period.
|
||||
filePeriod = 10 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("addr", ":8080", "http service address")
|
||||
homeTempl = template.Must(template.New("").Parse(homeHTML))
|
||||
filename string
|
||||
upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
)
|
||||
|
||||
func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) {
|
||||
fi, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return nil, lastMod, err
|
||||
}
|
||||
if !fi.ModTime().After(lastMod) {
|
||||
return nil, lastMod, nil
|
||||
}
|
||||
p, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fi.ModTime(), err
|
||||
}
|
||||
return p, fi.ModTime(), nil
|
||||
}
|
||||
|
||||
func reader(ws *websocket.Conn) {
|
||||
defer ws.Close()
|
||||
ws.SetReadLimit(512)
|
||||
ws.SetReadDeadline(time.Now().Add(pongWait))
|
||||
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
for {
|
||||
_, _, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writer(ws *websocket.Conn, lastMod time.Time) {
|
||||
lastError := ""
|
||||
pingTicker := time.NewTicker(pingPeriod)
|
||||
fileTicker := time.NewTicker(filePeriod)
|
||||
defer func() {
|
||||
pingTicker.Stop()
|
||||
fileTicker.Stop()
|
||||
ws.Close()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-fileTicker.C:
|
||||
var p []byte
|
||||
var err error
|
||||
|
||||
p, lastMod, err = readFileIfModified(lastMod)
|
||||
|
||||
if err != nil {
|
||||
if s := err.Error(); s != lastError {
|
||||
lastError = s
|
||||
p = []byte(lastError)
|
||||
}
|
||||
} else {
|
||||
lastError = ""
|
||||
}
|
||||
|
||||
if p != nil {
|
||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if err := ws.WriteMessage(websocket.TextMessage, p); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case <-pingTicker.C:
|
||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func serveWs(w http.ResponseWriter, r *http.Request) {
|
||||
ws, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
if _, ok := err.(websocket.HandshakeError); !ok {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var lastMod time.Time
|
||||
if n, err := strconv.ParseInt(r.FormValue("lastMod"), 16, 64); err == nil {
|
||||
lastMod = time.Unix(0, n)
|
||||
}
|
||||
|
||||
go writer(ws, lastMod)
|
||||
reader(ws)
|
||||
}
|
||||
|
||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.Error(w, "Not found", 404)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
p, lastMod, err := readFileIfModified(time.Time{})
|
||||
if err != nil {
|
||||
p = []byte(err.Error())
|
||||
lastMod = time.Unix(0, 0)
|
||||
}
|
||||
var v = struct {
|
||||
Host string
|
||||
Data string
|
||||
LastMod string
|
||||
}{
|
||||
r.Host,
|
||||
string(p),
|
||||
strconv.FormatInt(lastMod.UnixNano(), 16),
|
||||
}
|
||||
homeTempl.Execute(w, &v)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
log.Fatal("filename not specified")
|
||||
}
|
||||
filename = flag.Args()[0]
|
||||
http.HandleFunc("/", serveHome)
|
||||
http.HandleFunc("/ws", serveWs)
|
||||
if err := http.ListenAndServe(*addr, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
const homeHTML = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>WebSocket Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="fileData">{{.Data}}</pre>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var data = document.getElementById("fileData");
|
||||
var conn = new WebSocket("ws://{{.Host}}/ws?lastMod={{.LastMod}}");
|
||||
conn.onclose = function(evt) {
|
||||
data.textContent = 'Connection closed';
|
||||
}
|
||||
conn.onmessage = function(evt) {
|
||||
console.log('file updated');
|
||||
data.textContent = evt.data;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
119
vendor/github.com/gorilla/websocket/json_test.go
сгенерированный
поставляемый
Обычный файл
119
vendor/github.com/gorilla/websocket/json_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,119 @@
|
||||
// Copyright 2013 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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJSON(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
c := fakeNetConn{&buf, &buf}
|
||||
wc := newConn(c, true, 1024, 1024)
|
||||
rc := newConn(c, false, 1024, 1024)
|
||||
|
||||
var actual, expect struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
expect.A = 1
|
||||
expect.B = "hello"
|
||||
|
||||
if err := wc.WriteJSON(&expect); err != nil {
|
||||
t.Fatal("write", err)
|
||||
}
|
||||
|
||||
if err := rc.ReadJSON(&actual); err != nil {
|
||||
t.Fatal("read", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(&actual, &expect) {
|
||||
t.Fatal("equal", actual, expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPartialJSONRead(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
c := fakeNetConn{&buf, &buf}
|
||||
wc := newConn(c, true, 1024, 1024)
|
||||
rc := newConn(c, false, 1024, 1024)
|
||||
|
||||
var v struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
v.A = 1
|
||||
v.B = "hello"
|
||||
|
||||
messageCount := 0
|
||||
|
||||
// Partial JSON values.
|
||||
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := len(data) - 1; i >= 0; i-- {
|
||||
if err := wc.WriteMessage(TextMessage, data[:i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
messageCount++
|
||||
}
|
||||
|
||||
// Whitespace.
|
||||
|
||||
if err := wc.WriteMessage(TextMessage, []byte(" ")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
messageCount++
|
||||
|
||||
// Close.
|
||||
|
||||
if err := wc.WriteMessage(CloseMessage, FormatCloseMessage(CloseNormalClosure, "")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < messageCount; i++ {
|
||||
err := rc.ReadJSON(&v)
|
||||
if err != io.ErrUnexpectedEOF {
|
||||
t.Error("read", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
err = rc.ReadJSON(&v)
|
||||
if _, ok := err.(*CloseError); !ok {
|
||||
t.Error("final", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeprecatedJSON(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
c := fakeNetConn{&buf, &buf}
|
||||
wc := newConn(c, true, 1024, 1024)
|
||||
rc := newConn(c, false, 1024, 1024)
|
||||
|
||||
var actual, expect struct {
|
||||
A int
|
||||
B string
|
||||
}
|
||||
expect.A = 1
|
||||
expect.B = "hello"
|
||||
|
||||
if err := WriteJSON(wc, &expect); err != nil {
|
||||
t.Fatal("write", err)
|
||||
}
|
||||
|
||||
if err := ReadJSON(rc, &actual); err != nil {
|
||||
t.Fatal("read", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(&actual, &expect) {
|
||||
t.Fatal("equal", actual, expect)
|
||||
}
|
||||
}
|
||||
51
vendor/github.com/gorilla/websocket/server_test.go
сгенерированный
поставляемый
Обычный файл
51
vendor/github.com/gorilla/websocket/server_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,51 @@
|
||||
// Copyright 2013 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
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var subprotocolTests = []struct {
|
||||
h string
|
||||
protocols []string
|
||||
}{
|
||||
{"", nil},
|
||||
{"foo", []string{"foo"}},
|
||||
{"foo,bar", []string{"foo", "bar"}},
|
||||
{"foo, bar", []string{"foo", "bar"}},
|
||||
{" foo, bar", []string{"foo", "bar"}},
|
||||
{" foo, bar ", []string{"foo", "bar"}},
|
||||
}
|
||||
|
||||
func TestSubprotocols(t *testing.T) {
|
||||
for _, st := range subprotocolTests {
|
||||
r := http.Request{Header: http.Header{"Sec-Websocket-Protocol": {st.h}}}
|
||||
protocols := Subprotocols(&r)
|
||||
if !reflect.DeepEqual(st.protocols, protocols) {
|
||||
t.Errorf("SubProtocols(%q) returned %#v, want %#v", st.h, protocols, st.protocols)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isWebSocketUpgradeTests = []struct {
|
||||
ok bool
|
||||
h http.Header
|
||||
}{
|
||||
{false, http.Header{"Upgrade": {"websocket"}}},
|
||||
{false, http.Header{"Connection": {"upgrade"}}},
|
||||
{true, http.Header{"Connection": {"upgRade"}, "Upgrade": {"WebSocket"}}},
|
||||
}
|
||||
|
||||
func TestIsWebSocketUpgrade(t *testing.T) {
|
||||
for _, tt := range isWebSocketUpgradeTests {
|
||||
ok := IsWebSocketUpgrade(&http.Request{Header: tt.h})
|
||||
if tt.ok != ok {
|
||||
t.Errorf("IsWebSocketUpgrade(%v) returned %v, want %v", tt.h, ok, tt.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
34
vendor/github.com/gorilla/websocket/util_test.go
сгенерированный
поставляемый
Обычный файл
34
vendor/github.com/gorilla/websocket/util_test.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,34 @@
|
||||
// Copyright 2014 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
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var tokenListContainsValueTests = []struct {
|
||||
value string
|
||||
ok bool
|
||||
}{
|
||||
{"WebSocket", true},
|
||||
{"WEBSOCKET", true},
|
||||
{"websocket", true},
|
||||
{"websockets", false},
|
||||
{"x websocket", false},
|
||||
{"websocket x", false},
|
||||
{"other,websocket,more", true},
|
||||
{"other, websocket, more", true},
|
||||
}
|
||||
|
||||
func TestTokenListContainsValue(t *testing.T) {
|
||||
for _, tt := range tokenListContainsValueTests {
|
||||
h := http.Header{"Upgrade": {tt.value}}
|
||||
ok := tokenListContainsValue(h, "Upgrade", "websocket")
|
||||
if ok != tt.ok {
|
||||
t.Errorf("tokenListContainsValue(h, n, %q) = %v, want %v", tt.value, ok, tt.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user