From 701d1ab638b23c24877fc41824add66232446676 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 2 Feb 2017 09:32:00 -0500 Subject: Updating server dependancies (#5249) --- vendor/github.com/gorilla/handlers/recovery.go | 15 +++++--- vendor/github.com/gorilla/mux/README.md | 44 +++++++++++++++++++++- vendor/github.com/gorilla/mux/doc.go | 5 +++ vendor/github.com/gorilla/mux/mux_test.go | 10 +++++ vendor/github.com/gorilla/mux/regexp.go | 7 ++++ vendor/github.com/gorilla/websocket/compression.go | 26 +++++++++++-- vendor/github.com/gorilla/websocket/conn.go | 42 +++++++++++++-------- 7 files changed, 124 insertions(+), 25 deletions(-) (limited to 'vendor/github.com/gorilla') diff --git a/vendor/github.com/gorilla/handlers/recovery.go b/vendor/github.com/gorilla/handlers/recovery.go index 65b7de58a..b1be9dc83 100644 --- a/vendor/github.com/gorilla/handlers/recovery.go +++ b/vendor/github.com/gorilla/handlers/recovery.go @@ -6,9 +6,14 @@ import ( "runtime/debug" ) +// RecoveryHandlerLogger is an interface used by the recovering handler to print logs. +type RecoveryHandlerLogger interface { + Println(...interface{}) +} + type recoveryHandler struct { handler http.Handler - logger *log.Logger + logger RecoveryHandlerLogger printStack bool } @@ -46,7 +51,7 @@ func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler { // RecoveryLogger is a functional option to override // the default logger -func RecoveryLogger(logger *log.Logger) RecoveryOption { +func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption { return func(h http.Handler) { r := h.(*recoveryHandler) r.logger = logger @@ -73,11 +78,11 @@ func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { h.handler.ServeHTTP(w, req) } -func (h recoveryHandler) log(message interface{}) { +func (h recoveryHandler) log(v ...interface{}) { if h.logger != nil { - h.logger.Println(message) + h.logger.Println(v...) } else { - log.Println(message) + log.Println(v...) } if h.printStack { diff --git a/vendor/github.com/gorilla/mux/README.md b/vendor/github.com/gorilla/mux/README.md index fa79a6bc3..94d396ca4 100644 --- a/vendor/github.com/gorilla/mux/README.md +++ b/vendor/github.com/gorilla/mux/README.md @@ -23,6 +23,7 @@ The name mux stands for "HTTP request multiplexer". Like the standard `http.Serv * [Install](#install) * [Examples](#examples) * [Matching Routes](#matching-routes) +* [Listing Routes](#listing-routes) * [Static Files](#static-files) * [Registered URLs](#registered-urls) * [Full Example](#full-example) @@ -65,8 +66,11 @@ r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) The names are used to create a map of route variables which can be retrieved calling `mux.Vars()`: ```go -vars := mux.Vars(request) -category := vars["category"] +func ArticlesCategoryHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, "Category: %v\n", vars["category"]) +} ``` And this is all you need to know about the basic usage. More advanced options are explained below. @@ -164,6 +168,42 @@ s.HandleFunc("/{key}/", ProductHandler) s.HandleFunc("/{key}/details", ProductDetailsHandler) ``` +### Listing Routes + +Routes on a mux can be listed using the Router.Walk method—useful for generating documentation: + +```go +package main + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" +) + +func handler(w http.ResponseWriter, r *http.Request) { + return +} + +func main() { + r := mux.NewRouter() + r.HandleFunc("/", handler) + r.HandleFunc("/products", handler) + r.HandleFunc("/articles", handler) + r.HandleFunc("/articles/{id}", handler) + r.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { + t, err := route.GetPathTemplate() + if err != nil { + return err + } + fmt.Println(t) + return nil + }) + http.Handle("/", r) +} +``` + ### Static Files Note that the path provided to `PathPrefix()` represents a "wildcard": calling diff --git a/vendor/github.com/gorilla/mux/doc.go b/vendor/github.com/gorilla/mux/doc.go index e9573dd8a..00daf4a72 100644 --- a/vendor/github.com/gorilla/mux/doc.go +++ b/vendor/github.com/gorilla/mux/doc.go @@ -57,6 +57,11 @@ calling mux.Vars(): vars := mux.Vars(request) category := vars["category"] +Note that if any capturing groups are present, mux will panic() during parsing. To prevent +this, convert any capturing groups to non-capturing, e.g. change "/{sort:(asc|desc)}" to +"/{sort:(?:asc|desc)}". This is a change from prior versions which behaved unpredictably +when capturing groups were present. + And this is all you need to know about the basic usage. More advanced options are explained below. diff --git a/vendor/github.com/gorilla/mux/mux_test.go b/vendor/github.com/gorilla/mux/mux_test.go index b4b049efc..405aca6de 100644 --- a/vendor/github.com/gorilla/mux/mux_test.go +++ b/vendor/github.com/gorilla/mux/mux_test.go @@ -1389,6 +1389,16 @@ func TestSubrouterErrorHandling(t *testing.T) { } } +// See: https://github.com/gorilla/mux/issues/200 +func TestPanicOnCapturingGroups(t *testing.T) { + defer func() { + if recover() == nil { + t.Errorf("(Test that capturing groups now fail fast) Expected panic, however test completed sucessfully.\n") + } + }() + NewRouter().NewRoute().Path("/{type:(promo|special)}/{promoId}.json") +} + // ---------------------------------------------------------------------------- // Helpers // ---------------------------------------------------------------------------- diff --git a/vendor/github.com/gorilla/mux/regexp.go b/vendor/github.com/gorilla/mux/regexp.go index fd8fe3956..0189ad346 100644 --- a/vendor/github.com/gorilla/mux/regexp.go +++ b/vendor/github.com/gorilla/mux/regexp.go @@ -109,6 +109,13 @@ func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash, if errCompile != nil { return nil, errCompile } + + // Check for capturing groups which used to work in older versions + if reg.NumSubexp() != len(idxs)/2 { + panic(fmt.Sprintf("route %s contains capture groups in its regexp. ", template) + + "Only non-capturing groups are accepted: e.g. (?:pattern) instead of (pattern)") + } + // Done! return &routeRegexp{ template: template, diff --git a/vendor/github.com/gorilla/websocket/compression.go b/vendor/github.com/gorilla/websocket/compression.go index e2ac7617b..72c166b2a 100644 --- a/vendor/github.com/gorilla/websocket/compression.go +++ b/vendor/github.com/gorilla/websocket/compression.go @@ -1,4 +1,4 @@ -// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. +// 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. @@ -9,6 +9,11 @@ import ( "errors" "io" "strings" + "sync" +) + +var ( + flateWriterPool = sync.Pool{} ) func decompressNoContextTakeover(r io.Reader) io.Reader { @@ -17,13 +22,20 @@ func decompressNoContextTakeover(r io.Reader) io.Reader { "\x00\x00\xff\xff" + // Add final block to squelch unexpected EOF error from flate reader. "\x01\x00\x00\xff\xff" - return flate.NewReader(io.MultiReader(r, strings.NewReader(tail))) } func compressNoContextTakeover(w io.WriteCloser) (io.WriteCloser, error) { tw := &truncWriter{w: w} - fw, err := flate.NewWriter(tw, 3) + i := flateWriterPool.Get() + var fw *flate.Writer + var err error + if i == nil { + fw, err = flate.NewWriter(tw, 3) + } else { + fw = i.(*flate.Writer) + fw.Reset(tw) + } return &flateWrapper{fw: fw, tw: tw}, err } @@ -69,11 +81,19 @@ type flateWrapper struct { } func (w *flateWrapper) Write(p []byte) (int, error) { + if w.fw == nil { + return 0, errWriteClosed + } return w.fw.Write(p) } func (w *flateWrapper) Close() error { + if w.fw == nil { + return errWriteClosed + } err1 := w.fw.Flush() + flateWriterPool.Put(w.fw) + w.fw = nil if w.tw.p != [4]byte{0, 0, 0xff, 0xff} { return errors.New("websocket: internal error, unexpected bytes at end of flate stream") } diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go index b7a97bae9..ce7f0a615 100644 --- a/vendor/github.com/gorilla/websocket/conn.go +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -218,6 +218,7 @@ func isValidReceivedCloseCode(code int) bool { return validReceivedCloseCodes[code] || (code >= 3000 && code <= 4999) } +// The Conn type represents a WebSocket connection. type Conn struct { conn net.Conn isServer bool @@ -406,12 +407,7 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er return err } -// NextWriter returns a writer for the next message to send. The writer's Close -// method flushes the complete message to the network. -// -// There can be at most one open writer on a connection. NextWriter closes the -// previous writer if the application has not already done so. -func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { +func (c *Conn) prepWrite(messageType int) error { // Close previous writer if not already closed by the application. It's // probably better to return an error in this situation, but we cannot // change this without breaking existing applications. @@ -421,13 +417,22 @@ func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { } if !isControl(messageType) && !isData(messageType) { - return nil, errBadWriteOpCode + return errBadWriteOpCode } c.writeErrMu.Lock() err := c.writeErr c.writeErrMu.Unlock() - if err != nil { + return err +} + +// NextWriter returns a writer for the next message to send. The writer's Close +// method flushes the complete message to the network. +// +// There can be at most one open writer on a connection. NextWriter closes the +// previous writer if the application has not already done so. +func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { + if err := c.prepWrite(messageType); err != nil { return nil, err } @@ -652,16 +657,23 @@ func (w *messageWriter) Close() error { // WriteMessage is a helper method for getting a writer using NextWriter, // writing the message and closing the writer. func (c *Conn) WriteMessage(messageType int, data []byte) error { - w, err := c.NextWriter(messageType) - if err != nil { - return err - } - if mw, ok := w.(*messageWriter); ok && c.isServer { - // Optimize write as a single frame. + + if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) { + + // Fast path with no allocations and single frame. + + if err := c.prepWrite(messageType); err != nil { + return err + } + mw := messageWriter{c: c, frameType: messageType, pos: maxFrameHeaderSize} n := copy(c.writeBuf[mw.pos:], data) mw.pos += n data = data[n:] - err = mw.flushFrame(true, data) + return mw.flushFrame(true, data) + } + + w, err := c.NextWriter(messageType) + if err != nil { return err } if _, err = w.Write(data); err != nil { -- cgit v1.2.3-1-g7c22