Depenancy upgrades and movign to dep. (#8630)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
bf24f51c4e
Коммит
6e2cb00008
8
vendor/github.com/gorilla/context/.travis.yml
сгенерированный
поставляемый
8
vendor/github.com/gorilla/context/.travis.yml
сгенерированный
поставляемый
@@ -7,13 +7,13 @@ matrix:
|
||||
- go: 1.4
|
||||
- go: 1.5
|
||||
- go: 1.6
|
||||
- go: 1.7
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
|
||||
script:
|
||||
- go get -t -v ./...
|
||||
- diff -u <(echo -n) <(gofmt -d .)
|
||||
- go vet $(go list ./... | grep -v /vendor/)
|
||||
- go tool vet .
|
||||
- go test -v -race ./...
|
||||
|
||||
3
vendor/github.com/gorilla/context/README.md
сгенерированный
поставляемый
3
vendor/github.com/gorilla/context/README.md
сгенерированный
поставляемый
@@ -4,7 +4,4 @@ context
|
||||
|
||||
gorilla/context is a general purpose registry for global request variables.
|
||||
|
||||
> Note: gorilla/context, having been born well before `context.Context` existed, does not play well
|
||||
> with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`.
|
||||
|
||||
Read the full documentation here: http://www.gorillatoolkit.org/pkg/context
|
||||
|
||||
161
vendor/github.com/gorilla/context/context_test.go
сгенерированный
поставляемый
161
vendor/github.com/gorilla/context/context_test.go
сгенерированный
поставляемый
@@ -1,161 +0,0 @@
|
||||
// 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(len(values), 0)
|
||||
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)
|
||||
}
|
||||
6
vendor/github.com/gorilla/context/doc.go
сгенерированный
поставляемый
6
vendor/github.com/gorilla/context/doc.go
сгенерированный
поставляемый
@@ -5,12 +5,6 @@
|
||||
/*
|
||||
Package context stores values shared during a request lifetime.
|
||||
|
||||
Note: gorilla/context, having been born well before `context.Context` existed,
|
||||
does not play well > with the shallow copying of the request that
|
||||
[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext)
|
||||
(added to net/http Go 1.7 onwards) performs. You should either use *just*
|
||||
gorilla/context, or moving forward, the new `http.Request.Context()`.
|
||||
|
||||
For example, a router can set variables extracted from the URL and later
|
||||
application handlers can access those values, or it can be used to store
|
||||
sessions values to be saved at the end of a request. There are several
|
||||
|
||||
127
vendor/github.com/gorilla/handlers/canonical_test.go
сгенерированный
поставляемый
127
vendor/github.com/gorilla/handlers/canonical_test.go
сгенерированный
поставляемый
@@ -1,127 +0,0 @@
|
||||
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
сгенерированный
поставляемый
@@ -1,154 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
371
vendor/github.com/gorilla/handlers/cors_test.go
сгенерированный
поставляемый
371
vendor/github.com/gorilla/handlers/cors_test.go
сгенерированный
поставляемый
@@ -1,371 +0,0 @@
|
||||
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
|
||||
}
|
||||
|
||||
// Specially craft a CORS object.
|
||||
handleFunc := func(h http.Handler) http.Handler {
|
||||
c := &cors{
|
||||
allowedMethods: defaultCorsMethods,
|
||||
allowedHeaders: defaultCorsHeaders,
|
||||
allowedOrigins: []string{"http://a.example.com"},
|
||||
h: h,
|
||||
}
|
||||
AllowedOriginValidator(originValidator)(c)
|
||||
return c
|
||||
}
|
||||
|
||||
handleFunc(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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCORSAllowStar(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)
|
||||
// Because * is the default CORS policy (which is safe), we should be
|
||||
// expect a * returned here as the Access Control Allow Origin header
|
||||
if header != "*" {
|
||||
t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
|
||||
}
|
||||
|
||||
}
|
||||
34
vendor/github.com/gorilla/handlers/handlers_go18_test.go
сгенерированный
поставляемый
34
vendor/github.com/gorilla/handlers/handlers_go18_test.go
сгенерированный
поставляемый
@@ -1,34 +0,0 @@
|
||||
// +build go1.8
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoggingHandlerWithPush(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
if _, ok := w.(http.Pusher); !ok {
|
||||
t.Fatalf("%T from LoggingHandler does not satisfy http.Pusher interface when built with Go >=1.8", w)
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
logger := LoggingHandler(ioutil.Discard, handler)
|
||||
logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/"))
|
||||
}
|
||||
|
||||
func TestCombinedLoggingHandlerWithPush(t *testing.T) {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
if _, ok := w.(http.Pusher); !ok {
|
||||
t.Fatalf("%T from CombinedLoggingHandler does not satisfy http.Pusher interface when built with Go >=1.8", w)
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
logger := CombinedLoggingHandler(ioutil.Discard, handler)
|
||||
logger.ServeHTTP(httptest.NewRecorder(), newRequest("GET", "/"))
|
||||
}
|
||||
378
vendor/github.com/gorilla/handlers/handlers_test.go
сгенерированный
поставляемый
378
vendor/github.com/gorilla/handlers/handlers_test.go
сгенерированный
поставляемый
@@ -1,378 +0,0 @@
|
||||
// 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 TestMakeLogger(t *testing.T) {
|
||||
rec := httptest.NewRecorder()
|
||||
logger := makeLogger(rec)
|
||||
// initial status
|
||||
if logger.Status() != http.StatusOK {
|
||||
t.Fatalf("wrong status, got %d want %d", logger.Status(), http.StatusOK)
|
||||
}
|
||||
// WriteHeader
|
||||
logger.WriteHeader(http.StatusInternalServerError)
|
||||
if logger.Status() != http.StatusInternalServerError {
|
||||
t.Fatalf("wrong status, got %d want %d", logger.Status(), http.StatusInternalServerError)
|
||||
}
|
||||
// Write
|
||||
logger.Write([]byte(ok))
|
||||
if logger.Size() != len(ok) {
|
||||
t.Fatalf("wrong size, got %d want %d", logger.Size(), len(ok))
|
||||
}
|
||||
// Header
|
||||
logger.Header().Set("key", "value")
|
||||
if val := logger.Header().Get("key"); val != "value" {
|
||||
t.Fatalf("wrong header, got %s want %s", val, "value")
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
111
vendor/github.com/gorilla/handlers/proxy_headers_test.go
сгенерированный
поставляемый
111
vendor/github.com/gorilla/handlers/proxy_headers_test.go
сгенерированный
поставляемый
@@ -1,111 +0,0 @@
|
||||
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"},
|
||||
{xForwardedScheme, "https", "https"},
|
||||
{xForwardedScheme, "http", "http"},
|
||||
{xForwardedScheme, "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")
|
||||
r.Header.Set(xForwardedHost, "google.com")
|
||||
var (
|
||||
addr string
|
||||
proto string
|
||||
host string
|
||||
)
|
||||
ProxyHeaders(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
addr = r.RemoteAddr
|
||||
proto = r.URL.Scheme
|
||||
host = r.Host
|
||||
})).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))
|
||||
}
|
||||
if host != r.Header.Get(xForwardedHost) {
|
||||
t.Fatalf("wrong address: got %s want %s", host,
|
||||
r.Header.Get(xForwardedHost))
|
||||
}
|
||||
|
||||
}
|
||||
44
vendor/github.com/gorilla/handlers/recovery_test.go
сгенерированный
поставляемый
44
vendor/github.com/gorilla/handlers/recovery_test.go
сгенерированный
поставляемый
@@ -1,44 +0,0 @@
|
||||
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
сгенерированный
поставляемый
@@ -1,49 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
40
vendor/github.com/gorilla/mux/context_gorilla_test.go
сгенерированный
поставляемый
40
vendor/github.com/gorilla/mux/context_gorilla_test.go
сгенерированный
поставляемый
@@ -1,40 +0,0 @@
|
||||
// +build !go1.7
|
||||
|
||||
package mux
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/context"
|
||||
)
|
||||
|
||||
// Tests that the context is cleared or not cleared properly depending on
|
||||
// the configuration of the router
|
||||
func TestKeepContext(t *testing.T) {
|
||||
func1 := func(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
r := NewRouter()
|
||||
r.HandleFunc("/", func1).Name("func1")
|
||||
|
||||
req, _ := http.NewRequest("GET", "http://localhost/", nil)
|
||||
context.Set(req, "t", 1)
|
||||
|
||||
res := new(http.ResponseWriter)
|
||||
r.ServeHTTP(*res, req)
|
||||
|
||||
if _, ok := context.GetOk(req, "t"); ok {
|
||||
t.Error("Context should have been cleared at end of request")
|
||||
}
|
||||
|
||||
r.KeepContext = true
|
||||
|
||||
req, _ = http.NewRequest("GET", "http://localhost/", nil)
|
||||
context.Set(req, "t", 1)
|
||||
|
||||
r.ServeHTTP(*res, req)
|
||||
if _, ok := context.GetOk(req, "t"); !ok {
|
||||
t.Error("Context should NOT have been cleared at end of request")
|
||||
}
|
||||
|
||||
}
|
||||
32
vendor/github.com/gorilla/mux/context_native_test.go
сгенерированный
поставляемый
32
vendor/github.com/gorilla/mux/context_native_test.go
сгенерированный
поставляемый
@@ -1,32 +0,0 @@
|
||||
// +build go1.7
|
||||
|
||||
package mux
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNativeContextMiddleware(t *testing.T) {
|
||||
withTimeout := func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), time.Minute)
|
||||
defer cancel()
|
||||
h.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
r := NewRouter()
|
||||
r.Handle("/path/{foo}", withTimeout(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := Vars(r)
|
||||
if vars["foo"] != "bar" {
|
||||
t.Fatal("Expected foo var to be set")
|
||||
}
|
||||
})))
|
||||
|
||||
rec := NewRecorder()
|
||||
req := newRequest("GET", "/path/bar")
|
||||
r.ServeHTTP(rec, req)
|
||||
}
|
||||
51
vendor/github.com/gorilla/mux/example_route_test.go
сгенерированный
поставляемый
51
vendor/github.com/gorilla/mux/example_route_test.go
сгенерированный
поставляемый
@@ -1,51 +0,0 @@
|
||||
package mux_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// This example demonstrates setting a regular expression matcher for
|
||||
// the header value. A plain word will match any value that contains a
|
||||
// matching substring as if the pattern was wrapped with `.*`.
|
||||
func ExampleRoute_HeadersRegexp() {
|
||||
r := mux.NewRouter()
|
||||
route := r.NewRoute().HeadersRegexp("Accept", "html")
|
||||
|
||||
req1, _ := http.NewRequest("GET", "example.com", nil)
|
||||
req1.Header.Add("Accept", "text/plain")
|
||||
req1.Header.Add("Accept", "text/html")
|
||||
|
||||
req2, _ := http.NewRequest("GET", "example.com", nil)
|
||||
req2.Header.Set("Accept", "application/xhtml+xml")
|
||||
|
||||
matchInfo := &mux.RouteMatch{}
|
||||
fmt.Printf("Match: %v %q\n", route.Match(req1, matchInfo), req1.Header["Accept"])
|
||||
fmt.Printf("Match: %v %q\n", route.Match(req2, matchInfo), req2.Header["Accept"])
|
||||
// Output:
|
||||
// Match: true ["text/plain" "text/html"]
|
||||
// Match: true ["application/xhtml+xml"]
|
||||
}
|
||||
|
||||
// This example demonstrates setting a strict regular expression matcher
|
||||
// for the header value. Using the start and end of string anchors, the
|
||||
// value must be an exact match.
|
||||
func ExampleRoute_HeadersRegexp_exactMatch() {
|
||||
r := mux.NewRouter()
|
||||
route := r.NewRoute().HeadersRegexp("Origin", "^https://example.co$")
|
||||
|
||||
yes, _ := http.NewRequest("GET", "example.co", nil)
|
||||
yes.Header.Set("Origin", "https://example.co")
|
||||
|
||||
no, _ := http.NewRequest("GET", "example.co.uk", nil)
|
||||
no.Header.Set("Origin", "https://example.co.uk")
|
||||
|
||||
matchInfo := &mux.RouteMatch{}
|
||||
fmt.Printf("Match: %v %q\n", route.Match(yes, matchInfo), yes.Header["Origin"])
|
||||
fmt.Printf("Match: %v %q\n", route.Match(no, matchInfo), no.Header["Origin"])
|
||||
// Output:
|
||||
// Match: true ["https://example.co"]
|
||||
// Match: false ["https://example.co.uk"]
|
||||
}
|
||||
336
vendor/github.com/gorilla/mux/middleware_test.go
сгенерированный
поставляемый
336
vendor/github.com/gorilla/mux/middleware_test.go
сгенерированный
поставляемый
@@ -1,336 +0,0 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testMiddleware struct {
|
||||
timesCalled uint
|
||||
}
|
||||
|
||||
func (tm *testMiddleware) Middleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
tm.timesCalled++
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func dummyHandler(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
func TestMiddlewareAdd(t *testing.T) {
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", dummyHandler).Methods("GET")
|
||||
|
||||
mw := &testMiddleware{}
|
||||
|
||||
router.useInterface(mw)
|
||||
if len(router.middlewares) != 1 || router.middlewares[0] != mw {
|
||||
t.Fatal("Middleware was not added correctly")
|
||||
}
|
||||
|
||||
router.Use(mw.Middleware)
|
||||
if len(router.middlewares) != 2 {
|
||||
t.Fatal("MiddlewareFunc method was not added correctly")
|
||||
}
|
||||
|
||||
banalMw := func(handler http.Handler) http.Handler {
|
||||
return handler
|
||||
}
|
||||
router.Use(banalMw)
|
||||
if len(router.middlewares) != 3 {
|
||||
t.Fatal("MiddlewareFunc method was not added correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddleware(t *testing.T) {
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", dummyHandler).Methods("GET")
|
||||
|
||||
mw := &testMiddleware{}
|
||||
router.useInterface(mw)
|
||||
|
||||
rw := NewRecorder()
|
||||
req := newRequest("GET", "/")
|
||||
|
||||
// Test regular middleware call
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 1 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled)
|
||||
}
|
||||
|
||||
// Middleware should not be called for 404
|
||||
req = newRequest("GET", "/not/found")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 1 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled)
|
||||
}
|
||||
|
||||
// Middleware should not be called if there is a method mismatch
|
||||
req = newRequest("POST", "/")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 1 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled)
|
||||
}
|
||||
|
||||
// Add the middleware again as function
|
||||
router.Use(mw.Middleware)
|
||||
req = newRequest("GET", "/")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 3 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 3, mw.timesCalled)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMiddlewareSubrouter(t *testing.T) {
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", dummyHandler).Methods("GET")
|
||||
|
||||
subrouter := router.PathPrefix("/sub").Subrouter()
|
||||
subrouter.HandleFunc("/x", dummyHandler).Methods("GET")
|
||||
|
||||
mw := &testMiddleware{}
|
||||
subrouter.useInterface(mw)
|
||||
|
||||
rw := NewRecorder()
|
||||
req := newRequest("GET", "/")
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 0 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled)
|
||||
}
|
||||
|
||||
req = newRequest("GET", "/sub/")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 0 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 0, mw.timesCalled)
|
||||
}
|
||||
|
||||
req = newRequest("GET", "/sub/x")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 1 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled)
|
||||
}
|
||||
|
||||
req = newRequest("GET", "/sub/not/found")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 1 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 1, mw.timesCalled)
|
||||
}
|
||||
|
||||
router.useInterface(mw)
|
||||
|
||||
req = newRequest("GET", "/")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 2 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 2, mw.timesCalled)
|
||||
}
|
||||
|
||||
req = newRequest("GET", "/sub/x")
|
||||
router.ServeHTTP(rw, req)
|
||||
if mw.timesCalled != 4 {
|
||||
t.Fatalf("Expected %d calls, but got only %d", 4, mw.timesCalled)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddlewareExecution(t *testing.T) {
|
||||
mwStr := []byte("Middleware\n")
|
||||
handlerStr := []byte("Logic\n")
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
})
|
||||
|
||||
rw := NewRecorder()
|
||||
req := newRequest("GET", "/")
|
||||
|
||||
// Test handler-only call
|
||||
router.ServeHTTP(rw, req)
|
||||
|
||||
if bytes.Compare(rw.Body.Bytes(), handlerStr) != 0 {
|
||||
t.Fatal("Handler response is not what it should be")
|
||||
}
|
||||
|
||||
// Test middleware call
|
||||
rw = NewRecorder()
|
||||
|
||||
router.Use(func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(mwStr)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if bytes.Compare(rw.Body.Bytes(), append(mwStr, handlerStr...)) != 0 {
|
||||
t.Fatal("Middleware + handler response is not what it should be")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddlewareNotFound(t *testing.T) {
|
||||
mwStr := []byte("Middleware\n")
|
||||
handlerStr := []byte("Logic\n")
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
})
|
||||
router.Use(func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(mwStr)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
})
|
||||
|
||||
// Test not found call with default handler
|
||||
rw := NewRecorder()
|
||||
req := newRequest("GET", "/notfound")
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a 404")
|
||||
}
|
||||
|
||||
// Test not found call with custom handler
|
||||
rw = NewRecorder()
|
||||
req = newRequest("GET", "/notfound")
|
||||
|
||||
router.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Write([]byte("Custom 404 handler"))
|
||||
})
|
||||
router.ServeHTTP(rw, req)
|
||||
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a custom 404")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddlewareMethodMismatch(t *testing.T) {
|
||||
mwStr := []byte("Middleware\n")
|
||||
handlerStr := []byte("Logic\n")
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
}).Methods("GET")
|
||||
|
||||
router.Use(func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(mwStr)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
})
|
||||
|
||||
// Test method mismatch
|
||||
rw := NewRecorder()
|
||||
req := newRequest("POST", "/")
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a method mismatch")
|
||||
}
|
||||
|
||||
// Test not found call
|
||||
rw = NewRecorder()
|
||||
req = newRequest("POST", "/")
|
||||
|
||||
router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Write([]byte("Method not allowed"))
|
||||
})
|
||||
router.ServeHTTP(rw, req)
|
||||
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a method mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddlewareNotFoundSubrouter(t *testing.T) {
|
||||
mwStr := []byte("Middleware\n")
|
||||
handlerStr := []byte("Logic\n")
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
})
|
||||
|
||||
subrouter := router.PathPrefix("/sub/").Subrouter()
|
||||
subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
})
|
||||
|
||||
router.Use(func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(mwStr)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
})
|
||||
|
||||
// Test not found call for default handler
|
||||
rw := NewRecorder()
|
||||
req := newRequest("GET", "/sub/notfound")
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a 404")
|
||||
}
|
||||
|
||||
// Test not found call with custom handler
|
||||
rw = NewRecorder()
|
||||
req = newRequest("GET", "/sub/notfound")
|
||||
|
||||
subrouter.NotFoundHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Write([]byte("Custom 404 handler"))
|
||||
})
|
||||
router.ServeHTTP(rw, req)
|
||||
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a custom 404")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMiddlewareMethodMismatchSubrouter(t *testing.T) {
|
||||
mwStr := []byte("Middleware\n")
|
||||
handlerStr := []byte("Logic\n")
|
||||
|
||||
router := NewRouter()
|
||||
router.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
})
|
||||
|
||||
subrouter := router.PathPrefix("/sub/").Subrouter()
|
||||
subrouter.HandleFunc("/", func(w http.ResponseWriter, e *http.Request) {
|
||||
w.Write(handlerStr)
|
||||
}).Methods("GET")
|
||||
|
||||
router.Use(func(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(mwStr)
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
})
|
||||
|
||||
// Test method mismatch without custom handler
|
||||
rw := NewRecorder()
|
||||
req := newRequest("POST", "/sub/")
|
||||
|
||||
router.ServeHTTP(rw, req)
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a method mismatch")
|
||||
}
|
||||
|
||||
// Test method mismatch with custom handler
|
||||
rw = NewRecorder()
|
||||
req = newRequest("POST", "/sub/")
|
||||
|
||||
router.MethodNotAllowedHandler = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.Write([]byte("Method not allowed"))
|
||||
})
|
||||
router.ServeHTTP(rw, req)
|
||||
|
||||
if bytes.Contains(rw.Body.Bytes(), mwStr) {
|
||||
t.Fatal("Middleware was called for a method mismatch")
|
||||
}
|
||||
}
|
||||
2347
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
2347
vendor/github.com/gorilla/mux/mux_test.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
704
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
704
vendor/github.com/gorilla/mux/old_test.go
сгенерированный
поставляемый
@@ -1,704 +0,0 @@
|
||||
// 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 {
|
||||
t.Errorf("Expected: %v\nGot: %v\nRequest: %v %v", shouldMatch, matched, request.Method, url)
|
||||
}
|
||||
|
||||
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, regexpTypePath, routeRegexpOptions{})
|
||||
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])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
vendor/github.com/gorilla/schema/cache.go
сгенерированный
поставляемый
36
vendor/github.com/gorilla/schema/cache.go
сгенерированный
поставляемый
@@ -63,7 +63,7 @@ func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
|
||||
}
|
||||
// Valid field. Append index.
|
||||
path = append(path, field.name)
|
||||
if field.ss {
|
||||
if field.isSliceOfStructs && (!field.unmarshalerInfo.IsValid || (field.unmarshalerInfo.IsValid && field.unmarshalerInfo.IsSliceElement)) {
|
||||
// Parse a special case: slices of structs.
|
||||
// i+1 must be the slice index.
|
||||
//
|
||||
@@ -142,7 +142,7 @@ func (c *cache) create(t reflect.Type, info *structInfo) *structInfo {
|
||||
c.create(ft, info)
|
||||
for _, fi := range info.fields[bef:len(info.fields)] {
|
||||
// exclude required check because duplicated to embedded field
|
||||
fi.required = false
|
||||
fi.isRequired = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,7 @@ func (c *cache) createField(field reflect.StructField, info *structInfo) {
|
||||
// First let's get the basic type.
|
||||
isSlice, isStruct := false, false
|
||||
ft := field.Type
|
||||
m := isTextUnmarshaler(reflect.Zero(ft))
|
||||
if ft.Kind() == reflect.Ptr {
|
||||
ft = ft.Elem()
|
||||
}
|
||||
@@ -185,12 +186,13 @@ func (c *cache) createField(field reflect.StructField, info *structInfo) {
|
||||
}
|
||||
|
||||
info.fields = append(info.fields, &fieldInfo{
|
||||
typ: field.Type,
|
||||
name: field.Name,
|
||||
ss: isSlice && isStruct,
|
||||
alias: alias,
|
||||
anon: field.Anonymous,
|
||||
required: options.Contains("required"),
|
||||
typ: field.Type,
|
||||
name: field.Name,
|
||||
alias: alias,
|
||||
unmarshalerInfo: m,
|
||||
isSliceOfStructs: isSlice && isStruct,
|
||||
isAnonymous: field.Anonymous,
|
||||
isRequired: options.Contains("required"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -215,12 +217,18 @@ func (i *structInfo) get(alias string) *fieldInfo {
|
||||
}
|
||||
|
||||
type fieldInfo struct {
|
||||
typ reflect.Type
|
||||
name string // field name in the struct.
|
||||
ss bool // true if this is a slice of structs.
|
||||
alias string
|
||||
anon bool // is an embedded field
|
||||
required bool // tag option
|
||||
typ reflect.Type
|
||||
// name is the field name in the struct.
|
||||
name string
|
||||
alias string
|
||||
// unmarshalerInfo contains information regarding the
|
||||
// encoding.TextUnmarshaler implementation of the field type.
|
||||
unmarshalerInfo unmarshaler
|
||||
// isSliceOfStructs indicates if the field type is a slice of structs.
|
||||
isSliceOfStructs bool
|
||||
// isAnonymous indicates whether the field is embedded in the struct.
|
||||
isAnonymous bool
|
||||
isRequired bool
|
||||
}
|
||||
|
||||
type pathPart struct {
|
||||
|
||||
89
vendor/github.com/gorilla/schema/decoder.go
сгенерированный
поставляемый
89
vendor/github.com/gorilla/schema/decoder.go
сгенерированный
поставляемый
@@ -106,7 +106,7 @@ func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix
|
||||
if f.typ.Kind() == reflect.Struct {
|
||||
err := d.checkRequired(f.typ, src, prefix+f.alias+".")
|
||||
if err != nil {
|
||||
if !f.anon {
|
||||
if !f.isAnonymous {
|
||||
return err
|
||||
}
|
||||
// check embedded parent field.
|
||||
@@ -116,7 +116,7 @@ func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
if f.required {
|
||||
if f.isRequired {
|
||||
key := f.alias
|
||||
if prefix != "" {
|
||||
key = prefix + key
|
||||
@@ -185,7 +185,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
// Get the converter early in case there is one for a slice type.
|
||||
conv := d.cache.converter(t)
|
||||
m := isTextUnmarshaler(v)
|
||||
if conv == nil && t.Kind() == reflect.Slice && m.IsSlice {
|
||||
if conv == nil && t.Kind() == reflect.Slice && m.IsSliceElement {
|
||||
var items []reflect.Value
|
||||
elemT := t.Elem()
|
||||
isPtrElem := elemT.Kind() == reflect.Ptr
|
||||
@@ -211,7 +211,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
}
|
||||
} else if m.IsValid {
|
||||
u := reflect.New(elemT)
|
||||
if m.IsPtr {
|
||||
if m.IsSliceElementPtr {
|
||||
u = reflect.New(reflect.PtrTo(elemT).Elem())
|
||||
}
|
||||
if err := u.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(value)); err != nil {
|
||||
@@ -222,7 +222,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
if m.IsPtr {
|
||||
if m.IsSliceElementPtr {
|
||||
items = append(items, u.Elem().Addr())
|
||||
} else if u.Kind() == reflect.Ptr {
|
||||
items = append(items, u.Elem())
|
||||
@@ -283,11 +283,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
val = values[len(values)-1]
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
if d.zeroEmpty {
|
||||
v.Set(reflect.Zero(t))
|
||||
}
|
||||
} else if conv != nil {
|
||||
if conv != nil {
|
||||
if value := conv(val); value.IsValid() {
|
||||
v.Set(value.Convert(t))
|
||||
} else {
|
||||
@@ -298,15 +294,32 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
}
|
||||
}
|
||||
} else if m.IsValid {
|
||||
// If the value implements the encoding.TextUnmarshaler interface
|
||||
// apply UnmarshalText as the converter
|
||||
if err := m.Unmarshaler.UnmarshalText([]byte(val)); err != nil {
|
||||
return ConversionError{
|
||||
Key: path,
|
||||
Type: t,
|
||||
Index: -1,
|
||||
Err: err,
|
||||
if m.IsPtr {
|
||||
u := reflect.New(v.Type())
|
||||
if err := u.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(val)); err != nil {
|
||||
return ConversionError{
|
||||
Key: path,
|
||||
Type: t,
|
||||
Index: -1,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
v.Set(reflect.Indirect(u))
|
||||
} else {
|
||||
// If the value implements the encoding.TextUnmarshaler interface
|
||||
// apply UnmarshalText as the converter
|
||||
if err := m.Unmarshaler.UnmarshalText([]byte(val)); err != nil {
|
||||
return ConversionError{
|
||||
Key: path,
|
||||
Type: t,
|
||||
Index: -1,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if val == "" {
|
||||
if d.zeroEmpty {
|
||||
v.Set(reflect.Zero(t))
|
||||
}
|
||||
} else if conv := builtinConverters[t.Kind()]; conv != nil {
|
||||
if value := conv(val); value.IsValid() {
|
||||
@@ -326,18 +339,18 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
|
||||
}
|
||||
|
||||
func isTextUnmarshaler(v reflect.Value) unmarshaler {
|
||||
|
||||
// Create a new unmarshaller instance
|
||||
m := unmarshaler{}
|
||||
|
||||
// As the UnmarshalText function should be applied
|
||||
// to the pointer of the type, we convert the value to pointer.
|
||||
if v.CanAddr() {
|
||||
v = v.Addr()
|
||||
}
|
||||
if m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler); m.IsValid {
|
||||
return m
|
||||
}
|
||||
// As the UnmarshalText function should be applied to the pointer of the
|
||||
// type, we check that type to see if it implements the necessary
|
||||
// method.
|
||||
if m.Unmarshaler, m.IsValid = reflect.New(v.Type()).Interface().(encoding.TextUnmarshaler); m.IsValid {
|
||||
m.IsPtr = true
|
||||
return m
|
||||
}
|
||||
|
||||
// if v is []T or *[]T create new T
|
||||
t := v.Type()
|
||||
@@ -345,12 +358,17 @@ func isTextUnmarshaler(v reflect.Value) unmarshaler {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Kind() == reflect.Slice {
|
||||
// if t is a pointer slice, check if it implements encoding.TextUnmarshaler
|
||||
m.IsSlice = true
|
||||
// Check if the slice implements encoding.TextUnmarshaller
|
||||
if m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler); m.IsValid {
|
||||
return m
|
||||
}
|
||||
// If t is a pointer slice, check if its elements implement
|
||||
// encoding.TextUnmarshaler
|
||||
m.IsSliceElement = true
|
||||
if t = t.Elem(); t.Kind() == reflect.Ptr {
|
||||
t = reflect.PtrTo(t.Elem())
|
||||
v = reflect.Zero(t)
|
||||
m.IsPtr = true
|
||||
m.IsSliceElementPtr = true
|
||||
m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler)
|
||||
return m
|
||||
}
|
||||
@@ -365,9 +383,18 @@ func isTextUnmarshaler(v reflect.Value) unmarshaler {
|
||||
// unmarshaller contains information about a TextUnmarshaler type
|
||||
type unmarshaler struct {
|
||||
Unmarshaler encoding.TextUnmarshaler
|
||||
IsSlice bool
|
||||
IsPtr bool
|
||||
IsValid bool
|
||||
// IsValid indicates whether the resolved type indicated by the other
|
||||
// flags implements the encoding.TextUnmarshaler interface.
|
||||
IsValid bool
|
||||
// IsPtr indicates that the resolved type is the pointer of the original
|
||||
// type.
|
||||
IsPtr bool
|
||||
// IsSliceElement indicates that the resolved type is a slice element of
|
||||
// the original type.
|
||||
IsSliceElement bool
|
||||
// IsSliceElementPtr indicates that the resolved type is a pointer to a
|
||||
// slice element of the original type.
|
||||
IsSliceElementPtr bool
|
||||
}
|
||||
|
||||
// Errors ---------------------------------------------------------------------
|
||||
|
||||
1693
vendor/github.com/gorilla/schema/decoder_test.go
сгенерированный
поставляемый
1693
vendor/github.com/gorilla/schema/decoder_test.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
420
vendor/github.com/gorilla/schema/encoder_test.go
сгенерированный
поставляемый
420
vendor/github.com/gorilla/schema/encoder_test.go
сгенерированный
поставляемый
@@ -1,420 +0,0 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type E1 struct {
|
||||
F01 int `schema:"f01"`
|
||||
F02 int `schema:"-"`
|
||||
F03 string `schema:"f03"`
|
||||
F04 string `schema:"f04,omitempty"`
|
||||
F05 bool `schema:"f05"`
|
||||
F06 bool `schema:"f06"`
|
||||
F07 *string `schema:"f07"`
|
||||
F08 *int8 `schema:"f08"`
|
||||
F09 float64 `schema:"f09"`
|
||||
F10 func() `schema:"f10"`
|
||||
F11 inner
|
||||
}
|
||||
type inner struct {
|
||||
F12 int
|
||||
}
|
||||
|
||||
func TestFilled(t *testing.T) {
|
||||
f07 := "seven"
|
||||
var f08 int8 = 8
|
||||
s := &E1{
|
||||
F01: 1,
|
||||
F02: 2,
|
||||
F03: "three",
|
||||
F04: "four",
|
||||
F05: true,
|
||||
F06: false,
|
||||
F07: &f07,
|
||||
F08: &f08,
|
||||
F09: 1.618,
|
||||
F10: func() {},
|
||||
F11: inner{12},
|
||||
}
|
||||
|
||||
vals := make(map[string][]string)
|
||||
errs := NewEncoder().Encode(s, vals)
|
||||
|
||||
valExists(t, "f01", "1", vals)
|
||||
valNotExists(t, "f02", vals)
|
||||
valExists(t, "f03", "three", vals)
|
||||
valExists(t, "f05", "true", vals)
|
||||
valExists(t, "f06", "false", vals)
|
||||
valExists(t, "f07", "seven", vals)
|
||||
valExists(t, "f08", "8", vals)
|
||||
valExists(t, "f09", "1.618000", vals)
|
||||
valExists(t, "F12", "12", vals)
|
||||
|
||||
emptyErr := MultiError{}
|
||||
if errs.Error() == emptyErr.Error() {
|
||||
t.Errorf("Expected error got %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
type Aa int
|
||||
|
||||
type E3 struct {
|
||||
F01 bool `schema:"f01"`
|
||||
F02 float32 `schema:"f02"`
|
||||
F03 float64 `schema:"f03"`
|
||||
F04 int `schema:"f04"`
|
||||
F05 int8 `schema:"f05"`
|
||||
F06 int16 `schema:"f06"`
|
||||
F07 int32 `schema:"f07"`
|
||||
F08 int64 `schema:"f08"`
|
||||
F09 string `schema:"f09"`
|
||||
F10 uint `schema:"f10"`
|
||||
F11 uint8 `schema:"f11"`
|
||||
F12 uint16 `schema:"f12"`
|
||||
F13 uint32 `schema:"f13"`
|
||||
F14 uint64 `schema:"f14"`
|
||||
F15 Aa `schema:"f15"`
|
||||
}
|
||||
|
||||
// Test compatibility with default decoder types.
|
||||
func TestCompat(t *testing.T) {
|
||||
src := &E3{
|
||||
F01: true,
|
||||
F02: 4.2,
|
||||
F03: 4.3,
|
||||
F04: -42,
|
||||
F05: -43,
|
||||
F06: -44,
|
||||
F07: -45,
|
||||
F08: -46,
|
||||
F09: "foo",
|
||||
F10: 42,
|
||||
F11: 43,
|
||||
F12: 44,
|
||||
F13: 45,
|
||||
F14: 46,
|
||||
F15: 1,
|
||||
}
|
||||
dst := &E3{}
|
||||
|
||||
vals := make(map[string][]string)
|
||||
encoder := NewEncoder()
|
||||
decoder := NewDecoder()
|
||||
|
||||
encoder.RegisterEncoder(src.F15, func(reflect.Value) string { return "1" })
|
||||
decoder.RegisterConverter(src.F15, func(string) reflect.Value { return reflect.ValueOf(1) })
|
||||
|
||||
err := encoder.Encode(src, vals)
|
||||
if err != nil {
|
||||
t.Errorf("Encoder has non-nil error: %v", err)
|
||||
}
|
||||
err = decoder.Decode(dst, vals)
|
||||
if err != nil {
|
||||
t.Errorf("Decoder has non-nil error: %v", err)
|
||||
}
|
||||
|
||||
if *src != *dst {
|
||||
t.Errorf("Decoder-Encoder compatibility: expected %v, got %v\n", src, dst)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmpty(t *testing.T) {
|
||||
s := &E1{
|
||||
F01: 1,
|
||||
F02: 2,
|
||||
F03: "three",
|
||||
}
|
||||
|
||||
estr := "schema: encoder not found for <nil>"
|
||||
vals := make(map[string][]string)
|
||||
err := NewEncoder().Encode(s, vals)
|
||||
if err.Error() != estr {
|
||||
t.Errorf("Expected: %s, got %v", estr, err)
|
||||
}
|
||||
|
||||
valExists(t, "f03", "three", vals)
|
||||
valNotExists(t, "f04", vals)
|
||||
}
|
||||
|
||||
func TestStruct(t *testing.T) {
|
||||
estr := "schema: interface must be a struct"
|
||||
vals := make(map[string][]string)
|
||||
err := NewEncoder().Encode("hello world", vals)
|
||||
|
||||
if err.Error() != estr {
|
||||
t.Errorf("Expected: %s, got %v", estr, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlices(t *testing.T) {
|
||||
type oneAsWord int
|
||||
ones := []oneAsWord{1, 2}
|
||||
s1 := &struct {
|
||||
ones []oneAsWord `schema:"ones"`
|
||||
ints []int `schema:"ints"`
|
||||
nonempty []int `schema:"nonempty"`
|
||||
empty []int `schema:"empty,omitempty"`
|
||||
}{ones, []int{1, 1}, []int{}, []int{}}
|
||||
vals := make(map[string][]string)
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.RegisterEncoder(ones[0], func(v reflect.Value) string { return "one" })
|
||||
err := encoder.Encode(s1, vals)
|
||||
if err != nil {
|
||||
t.Errorf("Encoder has non-nil error: %v", err)
|
||||
}
|
||||
|
||||
valsExist(t, "ones", []string{"one", "one"}, vals)
|
||||
valsExist(t, "ints", []string{"1", "1"}, vals)
|
||||
valsExist(t, "nonempty", []string{}, vals)
|
||||
valNotExists(t, "empty", vals)
|
||||
}
|
||||
|
||||
func TestCompatSlices(t *testing.T) {
|
||||
type oneAsWord int
|
||||
type s1 struct {
|
||||
Ones []oneAsWord `schema:"ones"`
|
||||
Ints []int `schema:"ints"`
|
||||
}
|
||||
ones := []oneAsWord{1, 1}
|
||||
src := &s1{ones, []int{1, 1}}
|
||||
vals := make(map[string][]string)
|
||||
dst := &s1{}
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.RegisterEncoder(ones[0], func(v reflect.Value) string { return "one" })
|
||||
|
||||
decoder := NewDecoder()
|
||||
decoder.RegisterConverter(ones[0], func(s string) reflect.Value {
|
||||
if s == "one" {
|
||||
return reflect.ValueOf(1)
|
||||
}
|
||||
return reflect.ValueOf(2)
|
||||
})
|
||||
|
||||
err := encoder.Encode(src, vals)
|
||||
if err != nil {
|
||||
t.Errorf("Encoder has non-nil error: %v", err)
|
||||
}
|
||||
err = decoder.Decode(dst, vals)
|
||||
if err != nil {
|
||||
t.Errorf("Dncoder has non-nil error: %v", err)
|
||||
}
|
||||
|
||||
if len(src.Ints) != len(dst.Ints) || len(src.Ones) != len(src.Ones) {
|
||||
t.Fatalf("Expected %v, got %v", src, dst)
|
||||
}
|
||||
|
||||
for i, v := range src.Ones {
|
||||
if dst.Ones[i] != v {
|
||||
t.Fatalf("Expected %v, got %v", v, dst.Ones[i])
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range src.Ints {
|
||||
if dst.Ints[i] != v {
|
||||
t.Fatalf("Expected %v, got %v", v, dst.Ints[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterEncoder(t *testing.T) {
|
||||
type oneAsWord int
|
||||
type twoAsWord int
|
||||
type oneSliceAsWord []int
|
||||
|
||||
s1 := &struct {
|
||||
oneAsWord
|
||||
twoAsWord
|
||||
oneSliceAsWord
|
||||
}{1, 2, []int{1, 1}}
|
||||
v1 := make(map[string][]string)
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.RegisterEncoder(s1.oneAsWord, func(v reflect.Value) string { return "one" })
|
||||
encoder.RegisterEncoder(s1.twoAsWord, func(v reflect.Value) string { return "two" })
|
||||
encoder.RegisterEncoder(s1.oneSliceAsWord, func(v reflect.Value) string { return "one" })
|
||||
|
||||
err := encoder.Encode(s1, v1)
|
||||
if err != nil {
|
||||
t.Errorf("Encoder has non-nil error: %v", err)
|
||||
}
|
||||
|
||||
valExists(t, "oneAsWord", "one", v1)
|
||||
valExists(t, "twoAsWord", "two", v1)
|
||||
valExists(t, "oneSliceAsWord", "one", v1)
|
||||
}
|
||||
|
||||
func TestEncoderOrder(t *testing.T) {
|
||||
type builtinEncoderSimple int
|
||||
type builtinEncoderSimpleOverridden int
|
||||
type builtinEncoderSlice []int
|
||||
type builtinEncoderSliceOverridden []int
|
||||
type builtinEncoderStruct struct{ nr int }
|
||||
type builtinEncoderStructOverridden struct{ nr int }
|
||||
|
||||
s1 := &struct {
|
||||
builtinEncoderSimple `schema:"simple"`
|
||||
builtinEncoderSimpleOverridden `schema:"simple_overridden"`
|
||||
builtinEncoderSlice `schema:"slice"`
|
||||
builtinEncoderSliceOverridden `schema:"slice_overridden"`
|
||||
builtinEncoderStruct `schema:"struct"`
|
||||
builtinEncoderStructOverridden `schema:"struct_overridden"`
|
||||
}{
|
||||
1,
|
||||
1,
|
||||
[]int{2},
|
||||
[]int{2},
|
||||
builtinEncoderStruct{3},
|
||||
builtinEncoderStructOverridden{3},
|
||||
}
|
||||
v1 := make(map[string][]string)
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.RegisterEncoder(s1.builtinEncoderSimpleOverridden, func(v reflect.Value) string { return "one" })
|
||||
encoder.RegisterEncoder(s1.builtinEncoderSliceOverridden, func(v reflect.Value) string { return "two" })
|
||||
encoder.RegisterEncoder(s1.builtinEncoderStructOverridden, func(v reflect.Value) string { return "three" })
|
||||
|
||||
err := encoder.Encode(s1, v1)
|
||||
if err != nil {
|
||||
t.Errorf("Encoder has non-nil error: %v", err)
|
||||
}
|
||||
|
||||
valExists(t, "simple", "1", v1)
|
||||
valExists(t, "simple_overridden", "one", v1)
|
||||
valExists(t, "slice", "2", v1)
|
||||
valExists(t, "slice_overridden", "two", v1)
|
||||
valExists(t, "nr", "3", v1)
|
||||
valExists(t, "struct_overridden", "three", v1)
|
||||
}
|
||||
|
||||
func valExists(t *testing.T, key string, expect string, result map[string][]string) {
|
||||
valsExist(t, key, []string{expect}, result)
|
||||
}
|
||||
|
||||
func valsExist(t *testing.T, key string, expect []string, result map[string][]string) {
|
||||
vals, ok := result[key]
|
||||
if !ok {
|
||||
t.Fatalf("Key not found. Expected: %s", key)
|
||||
}
|
||||
|
||||
if len(expect) != len(vals) {
|
||||
t.Fatalf("Expected: %v, got: %v", expect, vals)
|
||||
}
|
||||
|
||||
for i, v := range expect {
|
||||
if vals[i] != v {
|
||||
t.Fatalf("Unexpected value. Expected: %v, got %v", v, vals[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func valNotExists(t *testing.T, key string, result map[string][]string) {
|
||||
if val, ok := result[key]; ok {
|
||||
t.Error("Key not ommited. Expected: empty; got: " + val[0] + ".")
|
||||
}
|
||||
}
|
||||
|
||||
type E4 struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func TestEncoderSetAliasTag(t *testing.T) {
|
||||
data := map[string][]string{}
|
||||
|
||||
s := E4{
|
||||
ID: "foo",
|
||||
}
|
||||
encoder := NewEncoder()
|
||||
encoder.SetAliasTag("json")
|
||||
encoder.Encode(&s, data)
|
||||
valExists(t, "id", "foo", data)
|
||||
}
|
||||
|
||||
type E5 struct {
|
||||
F01 int `schema:"f01,omitempty"`
|
||||
F02 string `schema:"f02,omitempty"`
|
||||
F03 *string `schema:"f03,omitempty"`
|
||||
F04 *int8 `schema:"f04,omitempty"`
|
||||
F05 float64 `schema:"f05,omitempty"`
|
||||
F06 E5F06 `schema:"f06,omitempty"`
|
||||
F07 E5F06 `schema:"f07,omitempty"`
|
||||
F08 []string `schema:"f08,omitempty"`
|
||||
F09 []string `schema:"f09,omitempty"`
|
||||
}
|
||||
|
||||
type E5F06 struct {
|
||||
F0601 string `schema:"f0601,omitempty"`
|
||||
}
|
||||
|
||||
func TestEncoderWithOmitempty(t *testing.T) {
|
||||
vals := map[string][]string{}
|
||||
|
||||
s := E5{
|
||||
F02: "test",
|
||||
F07: E5F06{
|
||||
F0601: "test",
|
||||
},
|
||||
F09: []string{"test"},
|
||||
}
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.Encode(&s, vals)
|
||||
|
||||
valNotExists(t, "f01", vals)
|
||||
valExists(t, "f02", "test", vals)
|
||||
valNotExists(t, "f03", vals)
|
||||
valNotExists(t, "f04", vals)
|
||||
valNotExists(t, "f05", vals)
|
||||
valNotExists(t, "f06", vals)
|
||||
valExists(t, "f0601", "test", vals)
|
||||
valNotExists(t, "f08", vals)
|
||||
valsExist(t, "f09", []string{"test"}, vals)
|
||||
}
|
||||
|
||||
type E6 struct {
|
||||
F01 *inner
|
||||
F02 *inner
|
||||
F03 *inner `schema:",omitempty"`
|
||||
}
|
||||
|
||||
func TestStructPointer(t *testing.T) {
|
||||
vals := map[string][]string{}
|
||||
s := E6{
|
||||
F01: &inner{2},
|
||||
}
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.Encode(&s, vals)
|
||||
valExists(t, "F12", "2", vals)
|
||||
valExists(t, "F02", "null", vals)
|
||||
valNotExists(t, "F03", vals)
|
||||
}
|
||||
|
||||
func TestRegisterEncoderCustomArrayType(t *testing.T) {
|
||||
type CustomInt []int
|
||||
type S1 struct {
|
||||
SomeInts CustomInt `schema:",omitempty"`
|
||||
}
|
||||
|
||||
ss := []S1{
|
||||
{},
|
||||
{CustomInt{}},
|
||||
{CustomInt{1, 2, 3}},
|
||||
}
|
||||
|
||||
for s := range ss {
|
||||
vals := map[string][]string{}
|
||||
|
||||
encoder := NewEncoder()
|
||||
encoder.RegisterEncoder(CustomInt{}, func(value reflect.Value) string {
|
||||
return fmt.Sprint(value.Interface())
|
||||
})
|
||||
|
||||
encoder.Encode(s, vals)
|
||||
t.Log(vals)
|
||||
}
|
||||
}
|
||||
2
vendor/github.com/gorilla/websocket/.gitignore
сгенерированный
поставляемый
2
vendor/github.com/gorilla/websocket/.gitignore
сгенерированный
поставляемый
@@ -22,4 +22,4 @@ _testmain.go
|
||||
*.exe
|
||||
|
||||
.idea/
|
||||
*.iml
|
||||
*.iml
|
||||
|
||||
11
vendor/github.com/gorilla/websocket/.travis.yml
сгенерированный
поставляемый
11
vendor/github.com/gorilla/websocket/.travis.yml
сгенерированный
поставляемый
@@ -4,11 +4,12 @@ sudo: false
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.4
|
||||
- go: 1.5
|
||||
- go: 1.6
|
||||
- go: 1.7
|
||||
- go: 1.8
|
||||
- go: 1.9
|
||||
- go: 1.5.x
|
||||
- go: 1.6.x
|
||||
- go: 1.7.x
|
||||
- go: 1.8.x
|
||||
- go: 1.9.x
|
||||
- go: 1.10.x
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
2
vendor/github.com/gorilla/websocket/README.md
сгенерированный
поставляемый
2
vendor/github.com/gorilla/websocket/README.md
сгенерированный
поставляемый
@@ -51,7 +51,7 @@ subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn
|
||||
<tr><td>Write message using io.WriteCloser</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextWriter">Yes</a></td><td>No, see note 3</td></tr>
|
||||
</table>
|
||||
|
||||
Notes:
|
||||
Notes:
|
||||
|
||||
1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
|
||||
2. The application can get the type of a received data message by implementing
|
||||
|
||||
12
vendor/github.com/gorilla/websocket/client.go
сгенерированный
поставляемый
12
vendor/github.com/gorilla/websocket/client.go
сгенерированный
поставляемый
@@ -106,9 +106,13 @@ func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) {
|
||||
|
||||
// DefaultDialer is a dialer with all fields set to the default values.
|
||||
var DefaultDialer = &Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
HandshakeTimeout: 45 * time.Second,
|
||||
}
|
||||
|
||||
// nilDialer is dialer to use when receiver is nil.
|
||||
var nilDialer Dialer = *DefaultDialer
|
||||
|
||||
// Dial creates a new client connection. Use requestHeader to specify the
|
||||
// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie).
|
||||
// Use the response.Header to get the selected subprotocol
|
||||
@@ -121,9 +125,7 @@ var DefaultDialer = &Dialer{
|
||||
func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) {
|
||||
|
||||
if d == nil {
|
||||
d = &Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
}
|
||||
d = &nilDialer
|
||||
}
|
||||
|
||||
challengeKey, err := generateChallengeKey()
|
||||
@@ -191,6 +193,8 @@ func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Re
|
||||
k == "Sec-Websocket-Extensions" ||
|
||||
(k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0):
|
||||
return nil, nil, errors.New("websocket: duplicate header not allowed: " + k)
|
||||
case k == "Sec-Websocket-Protocol":
|
||||
req.Header["Sec-WebSocket-Protocol"] = vs
|
||||
default:
|
||||
req.Header[k] = vs
|
||||
}
|
||||
|
||||
602
vendor/github.com/gorilla/websocket/client_server_test.go
сгенерированный
поставляемый
602
vendor/github.com/gorilla/websocket/client_server_test.go
сгенерированный
поставляемый
@@ -1,602 +0,0 @@
|
||||
// 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"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var cstUpgrader = Upgrader{
|
||||
Subprotocols: []string{"p0", "p1"},
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
EnableCompression: true,
|
||||
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,
|
||||
HandshakeTimeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
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.Server.URL)
|
||||
|
||||
cstDialer := cstDialer // make local copy for modification on next line.
|
||||
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 received")
|
||||
http.Error(w, "connect not received", 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)
|
||||
}
|
||||
|
||||
func TestProxyAuthorizationDial(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
surl, _ := url.Parse(s.Server.URL)
|
||||
surl.User = url.UserPassword("username", "password")
|
||||
|
||||
cstDialer := cstDialer // make local copy for modification on next line.
|
||||
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 received")
|
||||
http.Error(w, "connect with proxy authorization not received", 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)
|
||||
}
|
||||
|
||||
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 TestDialCookieJar(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
jar, _ := cookiejar.New(nil)
|
||||
d := cstDialer
|
||||
d.Jar = jar
|
||||
|
||||
u, _ := url.Parse(s.URL)
|
||||
|
||||
switch u.Scheme {
|
||||
case "ws":
|
||||
u.Scheme = "http"
|
||||
case "wss":
|
||||
u.Scheme = "https"
|
||||
}
|
||||
|
||||
cookies := []*http.Cookie{{Name: "gorilla", Value: "ws", Path: "/"}}
|
||||
d.Jar.SetCookies(u, cookies)
|
||||
|
||||
ws, _, err := d.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
var gorilla string
|
||||
var sessionID string
|
||||
for _, c := range d.Jar.Cookies(u) {
|
||||
if c.Name == "gorilla" {
|
||||
gorilla = c.Value
|
||||
}
|
||||
|
||||
if c.Name == "sessionID" {
|
||||
sessionID = c.Value
|
||||
}
|
||||
}
|
||||
if gorilla != "ws" {
|
||||
t.Error("Cookie not present in jar.")
|
||||
}
|
||||
|
||||
if sessionID != "1234" {
|
||||
t.Error("Set-Cookie not received from the server.")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
d := cstDialer
|
||||
d.TLSClientConfig = &tls.Config{RootCAs: certs}
|
||||
ws, _, err := d.Dial(s.URL, 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 TestDialTLSNoVerify(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()
|
||||
|
||||
req, err := http.NewRequest("POST", s.URL, strings.NewReader(""))
|
||||
if err != nil {
|
||||
t.Fatalf("NewRequest returned error %v", err)
|
||||
}
|
||||
req.Header.Set("Connection", "upgrade")
|
||||
req.Header.Set("Upgrade", "websocket")
|
||||
req.Header.Set("Sec-Websocket-Version", "13")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Do 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)
|
||||
}
|
||||
|
||||
func TestDialCompression(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
dialer := cstDialer
|
||||
dialer.EnableCompression = true
|
||||
ws, _, err := dialer.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
|
||||
func TestSocksProxyDial(t *testing.T) {
|
||||
s := newServer(t)
|
||||
defer s.Close()
|
||||
|
||||
proxyListener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen failed: %v", err)
|
||||
}
|
||||
defer proxyListener.Close()
|
||||
go func() {
|
||||
c1, err := proxyListener.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("proxy accept failed: %v", err)
|
||||
return
|
||||
}
|
||||
defer c1.Close()
|
||||
|
||||
c1.SetDeadline(time.Now().Add(30 * time.Second))
|
||||
|
||||
buf := make([]byte, 32)
|
||||
if _, err := io.ReadFull(c1, buf[:3]); err != nil {
|
||||
t.Errorf("read failed: %v", err)
|
||||
return
|
||||
}
|
||||
if want := []byte{5, 1, 0}; !bytes.Equal(want, buf[:len(want)]) {
|
||||
t.Errorf("read %x, want %x", buf[:len(want)], want)
|
||||
}
|
||||
if _, err := c1.Write([]byte{5, 0}); err != nil {
|
||||
t.Errorf("write failed: %v", err)
|
||||
return
|
||||
}
|
||||
if _, err := io.ReadFull(c1, buf[:10]); err != nil {
|
||||
t.Errorf("read failed: %v", err)
|
||||
return
|
||||
}
|
||||
if want := []byte{5, 1, 0, 1}; !bytes.Equal(want, buf[:len(want)]) {
|
||||
t.Errorf("read %x, want %x", buf[:len(want)], want)
|
||||
return
|
||||
}
|
||||
buf[1] = 0
|
||||
if _, err := c1.Write(buf[:10]); err != nil {
|
||||
t.Errorf("write failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
ip := net.IP(buf[4:8])
|
||||
port := binary.BigEndian.Uint16(buf[8:10])
|
||||
|
||||
c2, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: ip, Port: int(port)})
|
||||
if err != nil {
|
||||
t.Errorf("dial failed; %v", err)
|
||||
return
|
||||
}
|
||||
defer c2.Close()
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
io.Copy(c1, c2)
|
||||
close(done)
|
||||
}()
|
||||
io.Copy(c2, c1)
|
||||
<-done
|
||||
}()
|
||||
|
||||
purl, err := url.Parse("socks5://" + proxyListener.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed: %v", err)
|
||||
}
|
||||
|
||||
cstDialer := cstDialer // make local copy for modification on next line.
|
||||
cstDialer.Proxy = http.ProxyURL(purl)
|
||||
|
||||
ws, _, err := cstDialer.Dial(s.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
defer ws.Close()
|
||||
sendRecv(t, ws)
|
||||
}
|
||||
32
vendor/github.com/gorilla/websocket/client_test.go
сгенерированный
поставляемый
32
vendor/github.com/gorilla/websocket/client_test.go
сгенерированный
поставляемый
@@ -1,32 +0,0 @@
|
||||
// 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"
|
||||
"testing"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
80
vendor/github.com/gorilla/websocket/compression_test.go
сгенерированный
поставляемый
80
vendor/github.com/gorilla/websocket/compression_test.go
сгенерированный
поставляемый
@@ -1,80 +0,0 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type nopCloser struct{ io.Writer }
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
func TestTruncWriter(t *testing.T) {
|
||||
const data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlkmnopqrstuvwxyz987654321"
|
||||
for n := 1; n <= 10; n++ {
|
||||
var b bytes.Buffer
|
||||
w := &truncWriter{w: nopCloser{&b}}
|
||||
p := []byte(data)
|
||||
for len(p) > 0 {
|
||||
m := len(p)
|
||||
if m > n {
|
||||
m = n
|
||||
}
|
||||
w.Write(p[:m])
|
||||
p = p[m:]
|
||||
}
|
||||
if b.String() != data[:len(data)-len(w.p)] {
|
||||
t.Errorf("%d: %q", n, b.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func textMessages(num int) [][]byte {
|
||||
messages := make([][]byte, num)
|
||||
for i := 0; i < num; i++ {
|
||||
msg := fmt.Sprintf("planet: %d, country: %d, city: %d, street: %d", i, i, i, i)
|
||||
messages[i] = []byte(msg)
|
||||
}
|
||||
return messages
|
||||
}
|
||||
|
||||
func BenchmarkWriteNoCompression(b *testing.B) {
|
||||
w := ioutil.Discard
|
||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
||||
messages := textMessages(100)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.WriteMessage(TextMessage, messages[i%len(messages)])
|
||||
}
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func BenchmarkWriteWithCompression(b *testing.B) {
|
||||
w := ioutil.Discard
|
||||
c := newConn(fakeNetConn{Reader: nil, Writer: w}, false, 1024, 1024)
|
||||
messages := textMessages(100)
|
||||
c.enableWriteCompression = true
|
||||
c.newCompressionWriter = compressNoContextTakeover
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.WriteMessage(TextMessage, messages[i%len(messages)])
|
||||
}
|
||||
b.ReportAllocs()
|
||||
}
|
||||
|
||||
func TestValidCompressionLevel(t *testing.T) {
|
||||
c := newConn(fakeNetConn{}, false, 1024, 1024)
|
||||
for _, level := range []int{minCompressionLevel - 1, maxCompressionLevel + 1} {
|
||||
if err := c.SetCompressionLevel(level); err == nil {
|
||||
t.Errorf("no error for level %d", level)
|
||||
}
|
||||
}
|
||||
for _, level := range []int{minCompressionLevel, maxCompressionLevel} {
|
||||
if err := c.SetCompressionLevel(level); err != nil {
|
||||
t.Errorf("error for level %d", level)
|
||||
}
|
||||
}
|
||||
}
|
||||
17
vendor/github.com/gorilla/websocket/conn.go
сгенерированный
поставляемый
17
vendor/github.com/gorilla/websocket/conn.go
сгенерированный
поставляемый
@@ -370,7 +370,7 @@ func (c *Conn) writeFatal(err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Conn) write(frameType int, deadline time.Time, bufs ...[]byte) error {
|
||||
func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error {
|
||||
<-c.mu
|
||||
defer func() { c.mu <- true }()
|
||||
|
||||
@@ -382,15 +382,14 @@ func (c *Conn) write(frameType int, deadline time.Time, bufs ...[]byte) error {
|
||||
}
|
||||
|
||||
c.conn.SetWriteDeadline(deadline)
|
||||
for _, buf := range bufs {
|
||||
if len(buf) > 0 {
|
||||
_, err := c.conn.Write(buf)
|
||||
if err != nil {
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
}
|
||||
if len(buf1) == 0 {
|
||||
_, err = c.conn.Write(buf0)
|
||||
} else {
|
||||
err = c.writeBufs(buf0, buf1)
|
||||
}
|
||||
if err != nil {
|
||||
return c.writeFatal(err)
|
||||
}
|
||||
|
||||
if frameType == CloseMessage {
|
||||
c.writeFatal(ErrCloseSent)
|
||||
}
|
||||
|
||||
134
vendor/github.com/gorilla/websocket/conn_broadcast_test.go
сгенерированный
поставляемый
134
vendor/github.com/gorilla/websocket/conn_broadcast_test.go
сгенерированный
поставляемый
@@ -1,134 +0,0 @@
|
||||
// Copyright 2017 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 go1.7
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// broadcastBench allows to run broadcast benchmarks.
|
||||
// In every broadcast benchmark we create many connections, then send the same
|
||||
// message into every connection and wait for all writes complete. This emulates
|
||||
// an application where many connections listen to the same data - i.e. PUB/SUB
|
||||
// scenarios with many subscribers in one channel.
|
||||
type broadcastBench struct {
|
||||
w io.Writer
|
||||
message *broadcastMessage
|
||||
closeCh chan struct{}
|
||||
doneCh chan struct{}
|
||||
count int32
|
||||
conns []*broadcastConn
|
||||
compression bool
|
||||
usePrepared bool
|
||||
}
|
||||
|
||||
type broadcastMessage struct {
|
||||
payload []byte
|
||||
prepared *PreparedMessage
|
||||
}
|
||||
|
||||
type broadcastConn struct {
|
||||
conn *Conn
|
||||
msgCh chan *broadcastMessage
|
||||
}
|
||||
|
||||
func newBroadcastConn(c *Conn) *broadcastConn {
|
||||
return &broadcastConn{
|
||||
conn: c,
|
||||
msgCh: make(chan *broadcastMessage, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func newBroadcastBench(usePrepared, compression bool) *broadcastBench {
|
||||
bench := &broadcastBench{
|
||||
w: ioutil.Discard,
|
||||
doneCh: make(chan struct{}),
|
||||
closeCh: make(chan struct{}),
|
||||
usePrepared: usePrepared,
|
||||
compression: compression,
|
||||
}
|
||||
msg := &broadcastMessage{
|
||||
payload: textMessages(1)[0],
|
||||
}
|
||||
if usePrepared {
|
||||
pm, _ := NewPreparedMessage(TextMessage, msg.payload)
|
||||
msg.prepared = pm
|
||||
}
|
||||
bench.message = msg
|
||||
bench.makeConns(10000)
|
||||
return bench
|
||||
}
|
||||
|
||||
func (b *broadcastBench) makeConns(numConns int) {
|
||||
conns := make([]*broadcastConn, numConns)
|
||||
|
||||
for i := 0; i < numConns; i++ {
|
||||
c := newConn(fakeNetConn{Reader: nil, Writer: b.w}, true, 1024, 1024)
|
||||
if b.compression {
|
||||
c.enableWriteCompression = true
|
||||
c.newCompressionWriter = compressNoContextTakeover
|
||||
}
|
||||
conns[i] = newBroadcastConn(c)
|
||||
go func(c *broadcastConn) {
|
||||
for {
|
||||
select {
|
||||
case msg := <-c.msgCh:
|
||||
if b.usePrepared {
|
||||
c.conn.WritePreparedMessage(msg.prepared)
|
||||
} else {
|
||||
c.conn.WriteMessage(TextMessage, msg.payload)
|
||||
}
|
||||
val := atomic.AddInt32(&b.count, 1)
|
||||
if val%int32(numConns) == 0 {
|
||||
b.doneCh <- struct{}{}
|
||||
}
|
||||
case <-b.closeCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}(conns[i])
|
||||
}
|
||||
b.conns = conns
|
||||
}
|
||||
|
||||
func (b *broadcastBench) close() {
|
||||
close(b.closeCh)
|
||||
}
|
||||
|
||||
func (b *broadcastBench) runOnce() {
|
||||
for _, c := range b.conns {
|
||||
c.msgCh <- b.message
|
||||
}
|
||||
<-b.doneCh
|
||||
}
|
||||
|
||||
func BenchmarkBroadcast(b *testing.B) {
|
||||
benchmarks := []struct {
|
||||
name string
|
||||
usePrepared bool
|
||||
compression bool
|
||||
}{
|
||||
{"NoCompression", false, false},
|
||||
{"WithCompression", false, true},
|
||||
{"NoCompressionPrepared", true, false},
|
||||
{"WithCompressionPrepared", true, true},
|
||||
}
|
||||
for _, bm := range benchmarks {
|
||||
b.Run(bm.name, func(b *testing.B) {
|
||||
bench := newBroadcastBench(bm.usePrepared, bm.compression)
|
||||
defer bench.close()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
bench.runOnce()
|
||||
}
|
||||
b.ReportAllocs()
|
||||
})
|
||||
}
|
||||
}
|
||||
496
vendor/github.com/gorilla/websocket/conn_test.go
сгенерированный
поставляемый
496
vendor/github.com/gorilla/websocket/conn_test.go
сгенерированный
поставляемый
@@ -1,496 +0,0 @@
|
||||
// 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 localAddr }
|
||||
func (c fakeNetConn) RemoteAddr() net.Addr { return remoteAddr }
|
||||
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 }
|
||||
|
||||
type fakeAddr int
|
||||
|
||||
var (
|
||||
localAddr = fakeAddr(1)
|
||||
remoteAddr = fakeAddr(2)
|
||||
)
|
||||
|
||||
func (a fakeAddr) Network() string {
|
||||
return "net"
|
||||
}
|
||||
|
||||
func (a fakeAddr) String() string {
|
||||
return "str"
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
var writers = []struct {
|
||||
name string
|
||||
f func(w io.Writer, n int) (int, error)
|
||||
}{
|
||||
{"iocopy", func(w io.Writer, n int) (int, error) {
|
||||
nn, err := io.Copy(w, bytes.NewReader(writeBuf[:n]))
|
||||
return int(nn), err
|
||||
}},
|
||||
{"write", func(w io.Writer, n int) (int, error) {
|
||||
return w.Write(writeBuf[:n])
|
||||
}},
|
||||
{"string", func(w io.Writer, n int) (int, error) {
|
||||
return io.WriteString(w, string(writeBuf[:n]))
|
||||
}},
|
||||
}
|
||||
|
||||
for _, compress := range []bool{false, true} {
|
||||
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)
|
||||
if compress {
|
||||
wc.newCompressionWriter = compressNoContextTakeover
|
||||
rc.newDecompressionReader = decompressNoContextTakeover
|
||||
}
|
||||
for _, n := range frameSizes {
|
||||
for _, writer := range writers {
|
||||
name := fmt.Sprintf("z:%v, s:%v, r:%s, n:%d w:%s", compress, isServer, chunker.name, n, writer.name)
|
||||
|
||||
w, err := wc.NextWriter(TextMessage)
|
||||
if err != nil {
|
||||
t.Errorf("%s: wc.NextWriter() returned %v", name, err)
|
||||
continue
|
||||
}
|
||||
nn, err := writer.f(w, 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 TestCloseFrameBeforeFinalMessageFrame(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 TestWriteAfterMessageWriterClose(t *testing.T) {
|
||||
wc := newConn(fakeNetConn{Reader: nil, Writer: &bytes.Buffer{}}, false, 1024, 1024)
|
||||
w, _ := wc.NextWriter(BinaryMessage)
|
||||
io.WriteString(w, "hello")
|
||||
if err := w.Close(); err != nil {
|
||||
t.Fatalf("unxpected error closing message writer, %v", err)
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(w, "world"); err == nil {
|
||||
t.Fatalf("no error writing after close")
|
||||
}
|
||||
|
||||
w, _ = wc.NextWriter(BinaryMessage)
|
||||
io.WriteString(w, "hello")
|
||||
|
||||
// close w by getting next writer
|
||||
_, err := wc.NextWriter(BinaryMessage)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting next writer, %v", err)
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(w, "world"); err == nil {
|
||||
t.Fatalf("no error writing after close")
|
||||
}
|
||||
}
|
||||
|
||||
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 TestAddrs(t *testing.T) {
|
||||
c := newConn(&fakeNetConn{}, true, 1024, 1024)
|
||||
if c.LocalAddr() != localAddr {
|
||||
t.Errorf("LocalAddr = %v, want %v", c.LocalAddr(), localAddr)
|
||||
}
|
||||
if c.RemoteAddr() != remoteAddr {
|
||||
t.Errorf("RemoteAddr = %v, want %v", c.RemoteAddr(), remoteAddr)
|
||||
}
|
||||
}
|
||||
|
||||
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 returned %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")
|
||||
}
|
||||
|
||||
func TestBufioReuse(t *testing.T) {
|
||||
brw := bufio.NewReadWriter(bufio.NewReader(nil), bufio.NewWriter(nil))
|
||||
c := newConnBRW(nil, false, 0, 0, brw)
|
||||
|
||||
if c.br != brw.Reader {
|
||||
t.Error("connection did not reuse bufio.Reader")
|
||||
}
|
||||
|
||||
var wh writeHook
|
||||
brw.Writer.Reset(&wh)
|
||||
brw.WriteByte(0)
|
||||
brw.Flush()
|
||||
if &c.writeBuf[0] != &wh.p[0] {
|
||||
t.Error("connection did not reuse bufio.Writer")
|
||||
}
|
||||
|
||||
brw = bufio.NewReadWriter(bufio.NewReaderSize(nil, 0), bufio.NewWriterSize(nil, 0))
|
||||
c = newConnBRW(nil, false, 0, 0, brw)
|
||||
|
||||
if c.br == brw.Reader {
|
||||
t.Error("connection used bufio.Reader with small size")
|
||||
}
|
||||
|
||||
brw.Writer.Reset(&wh)
|
||||
brw.WriteByte(0)
|
||||
brw.Flush()
|
||||
if &c.writeBuf[0] != &wh.p[0] {
|
||||
t.Error("connection used bufio.Writer with small size")
|
||||
}
|
||||
|
||||
}
|
||||
15
vendor/github.com/gorilla/websocket/conn_write.go
сгенерированный
поставляемый
Обычный файл
15
vendor/github.com/gorilla/websocket/conn_write.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,15 @@
|
||||
// Copyright 2016 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 go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
import "net"
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
b := net.Buffers(bufs)
|
||||
_, err := b.WriteTo(c.conn)
|
||||
return err
|
||||
}
|
||||
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
сгенерированный
поставляемый
Обычный файл
18
vendor/github.com/gorilla/websocket/conn_write_legacy.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,18 @@
|
||||
// Copyright 2016 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 !go1.8
|
||||
|
||||
package websocket
|
||||
|
||||
func (c *Conn) writeBufs(bufs ...[]byte) error {
|
||||
for _, buf := range bufs {
|
||||
if len(buf) > 0 {
|
||||
if _, err := c.conn.Write(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
46
vendor/github.com/gorilla/websocket/example_test.go
сгенерированный
поставляемый
46
vendor/github.com/gorilla/websocket/example_test.go
сгенерированный
поставляемый
@@ -1,46 +0,0 @@
|
||||
// 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
сгенерированный
поставляемый
@@ -1,13 +0,0 @@
|
||||
# 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.
|
||||
15
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
сгенерированный
поставляемый
15
vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json
сгенерированный
поставляемый
@@ -1,15 +0,0 @@
|
||||
|
||||
{
|
||||
"options": {"failByDrop": false},
|
||||
"outdir": "./reports/clients",
|
||||
"servers": [
|
||||
{"agent": "ReadAllWriteMessage", "url": "ws://localhost:9000/m", "options": {"version": 18}},
|
||||
{"agent": "ReadAllWritePreparedMessage", "url": "ws://localhost:9000/p", "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": {}
|
||||
}
|
||||
265
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
сгенерированный
поставляемый
265
vendor/github.com/gorilla/websocket/examples/autobahn/server.go
сгенерированный
поставляемый
@@ -1,265 +0,0 @@
|
||||
// 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"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 4096,
|
||||
WriteBufferSize: 4096,
|
||||
EnableCompression: true,
|
||||
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, writePrepared 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 {
|
||||
if !writePrepared {
|
||||
err = conn.WriteMessage(mt, b)
|
||||
if err != nil {
|
||||
log.Println("WriteMessage:", err)
|
||||
}
|
||||
} else {
|
||||
pm, err := websocket.NewPreparedMessage(mt, b)
|
||||
if err != nil {
|
||||
log.Println("NewPreparedMessage:", err)
|
||||
return
|
||||
}
|
||||
err = conn.WritePreparedMessage(pm)
|
||||
if err != nil {
|
||||
log.Println("WritePreparedMessage:", 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, false)
|
||||
}
|
||||
|
||||
func echoReadAllWriteMessage(w http.ResponseWriter, r *http.Request) {
|
||||
echoReadAll(w, r, true, false)
|
||||
}
|
||||
|
||||
func echoReadAllWritePreparedMessage(w http.ResponseWriter, r *http.Request) {
|
||||
echoReadAll(w, r, true, 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)
|
||||
http.HandleFunc("/p", echoReadAllWritePreparedMessage)
|
||||
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
|
||||
}
|
||||
102
vendor/github.com/gorilla/websocket/examples/chat/README.md
сгенерированный
поставляемый
102
vendor/github.com/gorilla/websocket/examples/chat/README.md
сгенерированный
поставляемый
@@ -1,102 +0,0 @@
|
||||
# Chat Example
|
||||
|
||||
This application shows how to use the
|
||||
[websocket](https://github.com/gorilla/websocket) package 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.
|
||||
|
||||
## Server
|
||||
|
||||
The server application defines two types, `Client` and `Hub`. The server
|
||||
creates an instance of the `Client` type for each websocket connection. A
|
||||
`Client` acts as an intermediary between the websocket connection and a single
|
||||
instance of the `Hub` type. The `Hub` maintains a set of registered clients and
|
||||
broadcasts messages to the clients.
|
||||
|
||||
The application runs one goroutine for the `Hub` and two goroutines for each
|
||||
`Client`. The goroutines communicate with each other using channels. The `Hub`
|
||||
has channels for registering clients, unregistering clients and broadcasting
|
||||
messages. A `Client` has a buffered channel of outbound messages. One of the
|
||||
client's goroutines reads messages from this channel and writes the messages to
|
||||
the websocket. The other client goroutine reads messages from the websocket and
|
||||
sends them to the hub.
|
||||
|
||||
### Hub
|
||||
|
||||
The code for the `Hub` type is in
|
||||
[hub.go](https://github.com/gorilla/websocket/blob/master/examples/chat/hub.go).
|
||||
The application's `main` function starts the hub's `run` method as a goroutine.
|
||||
Clients send requests to the hub using the `register`, `unregister` and
|
||||
`broadcast` channels.
|
||||
|
||||
The hub registers clients by adding the client pointer as a key in the
|
||||
`clients` map. The map value is always true.
|
||||
|
||||
The unregister code is a little more complicated. In addition to deleting the
|
||||
client pointer from the `clients` map, the hub closes the clients's `send`
|
||||
channel to signal the client that no more messages will be sent to the client.
|
||||
|
||||
The hub handles messages by looping over the registered clients and sending the
|
||||
message to the client's `send` channel. If the client's `send` buffer is full,
|
||||
then the hub assumes that the client is dead or stuck. In this case, the hub
|
||||
unregisters the client and closes the websocket.
|
||||
|
||||
### Client
|
||||
|
||||
The code for the `Client` type is in [client.go](https://github.com/gorilla/websocket/blob/master/examples/chat/client.go).
|
||||
|
||||
The `serveWs` function is registered by the application's `main` function as
|
||||
an HTTP handler. The handler upgrades the HTTP connection to the WebSocket
|
||||
protocol, creates a client, registers the client with the hub and schedules the
|
||||
client to be unregistered using a defer statement.
|
||||
|
||||
Next, the HTTP handler starts the client's `writePump` method as a goroutine.
|
||||
This method transfers messages from the client's send channel to the websocket
|
||||
connection. The writer method exits when the channel is closed by the hub or
|
||||
there's an error writing to the websocket connection.
|
||||
|
||||
Finally, the HTTP handler calls the client's `readPump` method. This method
|
||||
transfers inbound messages from the websocket to the hub.
|
||||
|
||||
WebSocket connections [support one concurrent reader and one concurrent
|
||||
writer](https://godoc.org/github.com/gorilla/websocket#hdr-Concurrency). The
|
||||
application ensures that these concurrency requirements are met by executing
|
||||
all reads from the `readPump` goroutine and all writes from the `writePump`
|
||||
goroutine.
|
||||
|
||||
To improve efficiency under high load, the `writePump` function coalesces
|
||||
pending chat messages in the `send` channel to a single WebSocket message. This
|
||||
reduces the number of system calls and the amount of data sent over the
|
||||
network.
|
||||
|
||||
## Frontend
|
||||
|
||||
The frontend code is in [home.html](https://github.com/gorilla/websocket/blob/master/examples/chat/home.html).
|
||||
|
||||
On document load, the script checks for websocket functionality in the browser.
|
||||
If websocket functionality is available, then the script opens a connection to
|
||||
the server and registers a callback to handle messages from the server. The
|
||||
callback appends the message to the chat log using the appendLog function.
|
||||
|
||||
To allow the user to manually scroll through the chat log without interruption
|
||||
from new messages, the `appendLog` function checks the scroll position before
|
||||
adding new content. If the chat log is scrolled to the bottom, then the
|
||||
function scrolls new content into view after adding the content. Otherwise, the
|
||||
scroll position is not changed.
|
||||
|
||||
The form handler writes the user input to the websocket and clears the input
|
||||
field.
|
||||
137
vendor/github.com/gorilla/websocket/examples/chat/client.go
сгенерированный
поставляемый
137
vendor/github.com/gorilla/websocket/examples/chat/client.go
сгенерированный
поставляемый
@@ -1,137 +0,0 @@
|
||||
// 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 (
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
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 (
|
||||
newline = []byte{'\n'}
|
||||
space = []byte{' '}
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
// Client is a middleman between the websocket connection and the hub.
|
||||
type Client struct {
|
||||
hub *Hub
|
||||
|
||||
// The websocket connection.
|
||||
conn *websocket.Conn
|
||||
|
||||
// Buffered channel of outbound messages.
|
||||
send chan []byte
|
||||
}
|
||||
|
||||
// readPump pumps messages from the websocket connection to the hub.
|
||||
//
|
||||
// The application runs readPump in a per-connection goroutine. The application
|
||||
// ensures that there is at most one reader on a connection by executing all
|
||||
// reads from this goroutine.
|
||||
func (c *Client) readPump() {
|
||||
defer func() {
|
||||
c.hub.unregister <- c
|
||||
c.conn.Close()
|
||||
}()
|
||||
c.conn.SetReadLimit(maxMessageSize)
|
||||
c.conn.SetReadDeadline(time.Now().Add(pongWait))
|
||||
c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
|
||||
for {
|
||||
_, message, err := c.conn.ReadMessage()
|
||||
if err != nil {
|
||||
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||
log.Printf("error: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
|
||||
c.hub.broadcast <- message
|
||||
}
|
||||
}
|
||||
|
||||
// writePump pumps messages from the hub to the websocket connection.
|
||||
//
|
||||
// A goroutine running writePump is started for each connection. The
|
||||
// application ensures that there is at most one writer to a connection by
|
||||
// executing all writes from this goroutine.
|
||||
func (c *Client) writePump() {
|
||||
ticker := time.NewTicker(pingPeriod)
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
c.conn.Close()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case message, ok := <-c.send:
|
||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if !ok {
|
||||
// The hub closed the channel.
|
||||
c.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
||||
return
|
||||
}
|
||||
|
||||
w, err := c.conn.NextWriter(websocket.TextMessage)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
w.Write(message)
|
||||
|
||||
// Add queued chat messages to the current websocket message.
|
||||
n := len(c.send)
|
||||
for i := 0; i < n; i++ {
|
||||
w.Write(newline)
|
||||
w.Write(<-c.send)
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
case <-ticker.C:
|
||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// serveWs handles websocket requests from the peer.
|
||||
func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
|
||||
conn, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
|
||||
client.hub.register <- client
|
||||
|
||||
// Allow collection of memory referenced by the caller by doing all work in
|
||||
// new goroutines.
|
||||
go client.writePump()
|
||||
go client.readPump()
|
||||
}
|
||||
98
vendor/github.com/gorilla/websocket/examples/chat/home.html
сгенерированный
поставляемый
98
vendor/github.com/gorilla/websocket/examples/chat/home.html
сгенерированный
поставляемый
@@ -1,98 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Chat Example</title>
|
||||
<script type="text/javascript">
|
||||
window.onload = function () {
|
||||
var conn;
|
||||
var msg = document.getElementById("msg");
|
||||
var log = document.getElementById("log");
|
||||
|
||||
function appendLog(item) {
|
||||
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
||||
log.appendChild(item);
|
||||
if (doScroll) {
|
||||
log.scrollTop = log.scrollHeight - log.clientHeight;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("form").onsubmit = function () {
|
||||
if (!conn) {
|
||||
return false;
|
||||
}
|
||||
if (!msg.value) {
|
||||
return false;
|
||||
}
|
||||
conn.send(msg.value);
|
||||
msg.value = "";
|
||||
return false;
|
||||
};
|
||||
|
||||
if (window["WebSocket"]) {
|
||||
conn = new WebSocket("ws://" + document.location.host + "/ws");
|
||||
conn.onclose = function (evt) {
|
||||
var item = document.createElement("div");
|
||||
item.innerHTML = "<b>Connection closed.</b>";
|
||||
appendLog(item);
|
||||
};
|
||||
conn.onmessage = function (evt) {
|
||||
var messages = evt.data.split('\n');
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var item = document.createElement("div");
|
||||
item.innerText = messages[i];
|
||||
appendLog(item);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var item = document.createElement("div");
|
||||
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
|
||||
appendLog(item);
|
||||
}
|
||||
};
|
||||
</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>
|
||||
53
vendor/github.com/gorilla/websocket/examples/chat/hub.go
сгенерированный
поставляемый
53
vendor/github.com/gorilla/websocket/examples/chat/hub.go
сгенерированный
поставляемый
@@ -1,53 +0,0 @@
|
||||
// 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 clients and broadcasts messages to the
|
||||
// clients.
|
||||
type Hub struct {
|
||||
// Registered clients.
|
||||
clients map[*Client]bool
|
||||
|
||||
// Inbound messages from the clients.
|
||||
broadcast chan []byte
|
||||
|
||||
// Register requests from the clients.
|
||||
register chan *Client
|
||||
|
||||
// Unregister requests from clients.
|
||||
unregister chan *Client
|
||||
}
|
||||
|
||||
func newHub() *Hub {
|
||||
return &Hub{
|
||||
broadcast: make(chan []byte),
|
||||
register: make(chan *Client),
|
||||
unregister: make(chan *Client),
|
||||
clients: make(map[*Client]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hub) run() {
|
||||
for {
|
||||
select {
|
||||
case client := <-h.register:
|
||||
h.clients[client] = true
|
||||
case client := <-h.unregister:
|
||||
if _, ok := h.clients[client]; ok {
|
||||
delete(h.clients, client)
|
||||
close(client.send)
|
||||
}
|
||||
case message := <-h.broadcast:
|
||||
for client := range h.clients {
|
||||
select {
|
||||
case client.send <- message:
|
||||
default:
|
||||
close(client.send)
|
||||
delete(h.clients, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/github.com/gorilla/websocket/examples/chat/main.go
сгенерированный
поставляемый
40
vendor/github.com/gorilla/websocket/examples/chat/main.go
сгенерированный
поставляемый
@@ -1,40 +0,0 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
var addr = flag.String("addr", ":8080", "http service address")
|
||||
|
||||
func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println(r.URL)
|
||||
if r.URL.Path != "/" {
|
||||
http.Error(w, "Not found", 404)
|
||||
return
|
||||
}
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
return
|
||||
}
|
||||
http.ServeFile(w, r, "home.html")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
hub := newHub()
|
||||
go hub.run()
|
||||
http.HandleFunc("/", serveHome)
|
||||
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
|
||||
serveWs(hub, w, r)
|
||||
})
|
||||
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
сгенерированный
поставляемый
@@ -1,19 +0,0 @@
|
||||
# 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
|
||||
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
|
||||
|
||||
102
vendor/github.com/gorilla/websocket/examples/command/home.html
сгенерированный
поставляемый
102
vendor/github.com/gorilla/websocket/examples/command/home.html
сгенерированный
поставляемый
@@ -1,102 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Command Example</title>
|
||||
<script type="text/javascript">
|
||||
window.onload = function () {
|
||||
var conn;
|
||||
var msg = document.getElementById("msg");
|
||||
var log = document.getElementById("log");
|
||||
|
||||
function appendLog(item) {
|
||||
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
||||
log.appendChild(item);
|
||||
if (doScroll) {
|
||||
log.scrollTop = log.scrollHeight - log.clientHeight;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("form").onsubmit = function () {
|
||||
if (!conn) {
|
||||
return false;
|
||||
}
|
||||
if (!msg.value) {
|
||||
return false;
|
||||
}
|
||||
conn.send(msg.value);
|
||||
msg.value = "";
|
||||
return false;
|
||||
};
|
||||
|
||||
if (window["WebSocket"]) {
|
||||
conn = new WebSocket("ws://" + document.location.host + "/ws");
|
||||
conn.onclose = function (evt) {
|
||||
var item = document.createElement("div");
|
||||
item.innerHTML = "<b>Connection closed.</b>";
|
||||
appendLog(item);
|
||||
};
|
||||
conn.onmessage = function (evt) {
|
||||
var messages = evt.data.split('\n');
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var item = document.createElement("div");
|
||||
item.innerText = messages[i];
|
||||
appendLog(item);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var item = document.createElement("div");
|
||||
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
|
||||
appendLog(item);
|
||||
}
|
||||
};
|
||||
</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>
|
||||
193
vendor/github.com/gorilla/websocket/examples/command/main.go
сгенерированный
поставляемый
193
vendor/github.com/gorilla/websocket/examples/command/main.go
сгенерированный
поставляемый
@@ -1,193 +0,0 @@
|
||||
// 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"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var (
|
||||
addr = flag.String("addr", "127.0.0.1:8080", "http service address")
|
||||
cmdPath string
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
// Time to wait before force close on connection.
|
||||
closeGracePeriod = 10 * time.Second
|
||||
)
|
||||
|
||||
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() {
|
||||
}()
|
||||
s := bufio.NewScanner(r)
|
||||
for s.Scan() {
|
||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
if err := ws.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
|
||||
ws.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
if s.Err() != nil {
|
||||
log.Println("scan:", s.Err())
|
||||
}
|
||||
close(done)
|
||||
|
||||
ws.SetWriteDeadline(time.Now().Add(writeWait))
|
||||
ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
time.Sleep(closeGracePeriod)
|
||||
ws.Close()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
http.ServeFile(w, r, "home.html")
|
||||
}
|
||||
|
||||
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
сгенерированный
поставляемый
@@ -1,17 +0,0 @@
|
||||
# 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
сгенерированный
поставляемый
@@ -1,81 +0,0 @@
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
133
vendor/github.com/gorilla/websocket/examples/echo/server.go
сгенерированный
поставляемый
133
vendor/github.com/gorilla/websocket/examples/echo/server.go
сгенерированный
поставляемый
@@ -1,133 +0,0 @@
|
||||
// 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>
|
||||
<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
сгенерированный
поставляемый
@@ -1,9 +0,0 @@
|
||||
# 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
сгенерированный
поставляемый
@@ -1,193 +0,0 @@
|
||||
// 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"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"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
сгенерированный
поставляемый
@@ -1,119 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
73
vendor/github.com/gorilla/websocket/mask_test.go
сгенерированный
поставляемый
73
vendor/github.com/gorilla/websocket/mask_test.go
сгенерированный
поставляемый
@@ -1,73 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Require 1.7 for sub-bencmarks
|
||||
// +build go1.7,!appengine
|
||||
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func maskBytesByByte(key [4]byte, pos int, b []byte) int {
|
||||
for i := range b {
|
||||
b[i] ^= key[pos&3]
|
||||
pos++
|
||||
}
|
||||
return pos & 3
|
||||
}
|
||||
|
||||
func notzero(b []byte) int {
|
||||
for i := range b {
|
||||
if b[i] != 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func TestMaskBytes(t *testing.T) {
|
||||
key := [4]byte{1, 2, 3, 4}
|
||||
for size := 1; size <= 1024; size++ {
|
||||
for align := 0; align < wordSize; align++ {
|
||||
for pos := 0; pos < 4; pos++ {
|
||||
b := make([]byte, size+align)[align:]
|
||||
maskBytes(key, pos, b)
|
||||
maskBytesByByte(key, pos, b)
|
||||
if i := notzero(b); i >= 0 {
|
||||
t.Errorf("size:%d, align:%d, pos:%d, offset:%d", size, align, pos, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMaskBytes(b *testing.B) {
|
||||
for _, size := range []int{2, 4, 8, 16, 32, 512, 1024} {
|
||||
b.Run(fmt.Sprintf("size-%d", size), func(b *testing.B) {
|
||||
for _, align := range []int{wordSize / 2} {
|
||||
b.Run(fmt.Sprintf("align-%d", align), func(b *testing.B) {
|
||||
for _, fn := range []struct {
|
||||
name string
|
||||
fn func(key [4]byte, pos int, b []byte) int
|
||||
}{
|
||||
{"byte", maskBytesByByte},
|
||||
{"word", maskBytes},
|
||||
} {
|
||||
b.Run(fn.name, func(b *testing.B) {
|
||||
key := newMaskKey()
|
||||
data := make([]byte, size+align)[align:]
|
||||
for i := 0; i < b.N; i++ {
|
||||
fn.fn(key, 0, data)
|
||||
}
|
||||
b.SetBytes(int64(len(data)))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
74
vendor/github.com/gorilla/websocket/prepared_test.go
сгенерированный
поставляемый
74
vendor/github.com/gorilla/websocket/prepared_test.go
сгенерированный
поставляемый
@@ -1,74 +0,0 @@
|
||||
// Copyright 2017 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"
|
||||
"compress/flate"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var preparedMessageTests = []struct {
|
||||
messageType int
|
||||
isServer bool
|
||||
enableWriteCompression bool
|
||||
compressionLevel int
|
||||
}{
|
||||
// Server
|
||||
{TextMessage, true, false, flate.BestSpeed},
|
||||
{TextMessage, true, true, flate.BestSpeed},
|
||||
{TextMessage, true, true, flate.BestCompression},
|
||||
{PingMessage, true, false, flate.BestSpeed},
|
||||
{PingMessage, true, true, flate.BestSpeed},
|
||||
|
||||
// Client
|
||||
{TextMessage, false, false, flate.BestSpeed},
|
||||
{TextMessage, false, true, flate.BestSpeed},
|
||||
{TextMessage, false, true, flate.BestCompression},
|
||||
{PingMessage, false, false, flate.BestSpeed},
|
||||
{PingMessage, false, true, flate.BestSpeed},
|
||||
}
|
||||
|
||||
func TestPreparedMessage(t *testing.T) {
|
||||
for _, tt := range preparedMessageTests {
|
||||
var data = []byte("this is a test")
|
||||
var buf bytes.Buffer
|
||||
c := newConn(fakeNetConn{Reader: nil, Writer: &buf}, tt.isServer, 1024, 1024)
|
||||
if tt.enableWriteCompression {
|
||||
c.newCompressionWriter = compressNoContextTakeover
|
||||
}
|
||||
c.SetCompressionLevel(tt.compressionLevel)
|
||||
|
||||
// Seed random number generator for consistent frame mask.
|
||||
rand.Seed(1234)
|
||||
|
||||
if err := c.WriteMessage(tt.messageType, data); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := buf.String()
|
||||
|
||||
pm, err := NewPreparedMessage(tt.messageType, data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Scribble on data to ensure that NewPreparedMessage takes a snapshot.
|
||||
copy(data, "hello world")
|
||||
|
||||
// Seed random number generator for consistent frame mask.
|
||||
rand.Seed(1234)
|
||||
|
||||
buf.Reset()
|
||||
if err := c.WritePreparedMessage(pm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := buf.String()
|
||||
|
||||
if got != want {
|
||||
t.Errorf("write message != prepared message for %+v", tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
2
vendor/github.com/gorilla/websocket/server.go
сгенерированный
поставляемый
2
vendor/github.com/gorilla/websocket/server.go
сгенерированный
поставляемый
@@ -243,7 +243,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
|
||||
// of the same origin policy check is:
|
||||
//
|
||||
// if req.Header.Get("Origin") != "http://"+req.Host {
|
||||
// http.Error(w, "Origin not allowed", 403)
|
||||
// http.Error(w, "Origin not allowed", http.StatusForbidden)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
|
||||
69
vendor/github.com/gorilla/websocket/server_test.go
сгенерированный
поставляемый
69
vendor/github.com/gorilla/websocket/server_test.go
сгенерированный
поставляемый
@@ -1,69 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var checkSameOriginTests = []struct {
|
||||
ok bool
|
||||
r *http.Request
|
||||
}{
|
||||
{false, &http.Request{Host: "example.org", Header: map[string][]string{"Origin": []string{"https://other.org"}}}},
|
||||
{true, &http.Request{Host: "example.org", Header: map[string][]string{"Origin": []string{"https://example.org"}}}},
|
||||
{true, &http.Request{Host: "Example.org", Header: map[string][]string{"Origin": []string{"https://example.org"}}}},
|
||||
}
|
||||
|
||||
func TestCheckSameOrigin(t *testing.T) {
|
||||
for _, tt := range checkSameOriginTests {
|
||||
ok := checkSameOrigin(tt.r)
|
||||
if tt.ok != ok {
|
||||
t.Errorf("checkSameOrigin(%+v) returned %v, want %v", tt.r, ok, tt.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
95
vendor/github.com/gorilla/websocket/util_test.go
сгенерированный
поставляемый
95
vendor/github.com/gorilla/websocket/util_test.go
сгенерированный
поставляемый
@@ -1,95 +0,0 @@
|
||||
// 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"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var equalASCIIFoldTests = []struct {
|
||||
t, s string
|
||||
eq bool
|
||||
}{
|
||||
{"WebSocket", "websocket", true},
|
||||
{"websocket", "WebSocket", true},
|
||||
{"Öyster", "öyster", false},
|
||||
}
|
||||
|
||||
func TestEqualASCIIFold(t *testing.T) {
|
||||
for _, tt := range equalASCIIFoldTests {
|
||||
eq := equalASCIIFold(tt.s, tt.t)
|
||||
if eq != tt.eq {
|
||||
t.Errorf("equalASCIIFold(%q, %q) = %v, want %v", tt.s, tt.t, eq, tt.eq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var parseExtensionTests = []struct {
|
||||
value string
|
||||
extensions []map[string]string
|
||||
}{
|
||||
{`foo`, []map[string]string{{"": "foo"}}},
|
||||
{`foo, bar; baz=2`, []map[string]string{
|
||||
{"": "foo"},
|
||||
{"": "bar", "baz": "2"}}},
|
||||
{`foo; bar="b,a;z"`, []map[string]string{
|
||||
{"": "foo", "bar": "b,a;z"}}},
|
||||
{`foo , bar; baz = 2`, []map[string]string{
|
||||
{"": "foo"},
|
||||
{"": "bar", "baz": "2"}}},
|
||||
{`foo, bar; baz=2 junk`, []map[string]string{
|
||||
{"": "foo"}}},
|
||||
{`foo junk, bar; baz=2 junk`, nil},
|
||||
{`mux; max-channels=4; flow-control, deflate-stream`, []map[string]string{
|
||||
{"": "mux", "max-channels": "4", "flow-control": ""},
|
||||
{"": "deflate-stream"}}},
|
||||
{`permessage-foo; x="10"`, []map[string]string{
|
||||
{"": "permessage-foo", "x": "10"}}},
|
||||
{`permessage-foo; use_y, permessage-foo`, []map[string]string{
|
||||
{"": "permessage-foo", "use_y": ""},
|
||||
{"": "permessage-foo"}}},
|
||||
{`permessage-deflate; client_max_window_bits; server_max_window_bits=10 , permessage-deflate; client_max_window_bits`, []map[string]string{
|
||||
{"": "permessage-deflate", "client_max_window_bits": "", "server_max_window_bits": "10"},
|
||||
{"": "permessage-deflate", "client_max_window_bits": ""}}},
|
||||
{"permessage-deflate; server_no_context_takeover; client_max_window_bits=15", []map[string]string{
|
||||
{"": "permessage-deflate", "server_no_context_takeover": "", "client_max_window_bits": "15"},
|
||||
}},
|
||||
}
|
||||
|
||||
func TestParseExtensions(t *testing.T) {
|
||||
for _, tt := range parseExtensionTests {
|
||||
h := http.Header{http.CanonicalHeaderKey("Sec-WebSocket-Extensions"): {tt.value}}
|
||||
extensions := parseExtensions(h)
|
||||
if !reflect.DeepEqual(extensions, tt.extensions) {
|
||||
t.Errorf("parseExtensions(%q)\n = %v,\nwant %v", tt.value, extensions, tt.extensions)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user