mirror of
https://github.com/labstack/echo.git
synced 2024-11-24 08:22:21 +02:00
Now using sync.Pool
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
parent
443a0bb48d
commit
f405794a7c
@ -47,7 +47,7 @@ type (
|
||||
Redirect(int, string) error
|
||||
Error(err error)
|
||||
Logger() *log.Logger
|
||||
X() *context
|
||||
Context() *context
|
||||
}
|
||||
|
||||
context struct {
|
||||
@ -307,8 +307,8 @@ func (c *context) Logger() *log.Logger {
|
||||
return c.echo.logger
|
||||
}
|
||||
|
||||
// X returns the `context` instance.
|
||||
func (c *context) X() *context {
|
||||
// Context returns the `context` instance.
|
||||
func (c *context) Context() *context {
|
||||
return c
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ func TestContext(t *testing.T) {
|
||||
assert.Nil(t, c.Socket())
|
||||
|
||||
// Param by id
|
||||
c.X().pnames = []string{"id"}
|
||||
c.X().pvalues = []string{"1"}
|
||||
c.Context().pnames = []string{"id"}
|
||||
c.Context().pvalues = []string{"1"}
|
||||
assert.Equal(t, "1", c.P(0))
|
||||
|
||||
// Param by name
|
||||
@ -68,13 +68,13 @@ func TestContext(t *testing.T) {
|
||||
|
||||
// JSON
|
||||
testBindOk(t, c, ApplicationJSON)
|
||||
c.X().request = test.NewRequest(POST, "/", strings.NewReader(incorrectContent))
|
||||
c.Context().request = test.NewRequest(POST, "/", strings.NewReader(incorrectContent))
|
||||
testBindError(t, c, ApplicationJSON)
|
||||
|
||||
// XML
|
||||
c.X().request = test.NewRequest(POST, "/", strings.NewReader(userXML))
|
||||
c.Context().request = test.NewRequest(POST, "/", strings.NewReader(userXML))
|
||||
testBindOk(t, c, ApplicationXML)
|
||||
c.X().request = test.NewRequest(POST, "/", strings.NewReader(incorrectContent))
|
||||
c.Context().request = test.NewRequest(POST, "/", strings.NewReader(incorrectContent))
|
||||
testBindError(t, c, ApplicationXML)
|
||||
|
||||
// Unsupported
|
||||
@ -87,14 +87,14 @@ func TestContext(t *testing.T) {
|
||||
tpl := &Template{
|
||||
templates: template.Must(template.New("hello").Parse("Hello, {{.}}!")),
|
||||
}
|
||||
c.X().echo.SetRenderer(tpl)
|
||||
c.Context().echo.SetRenderer(tpl)
|
||||
err := c.Render(http.StatusOK, "hello", "Joe")
|
||||
if assert.NoError(t, err) {
|
||||
assert.Equal(t, http.StatusOK, rec.Status())
|
||||
assert.Equal(t, "Hello, Joe!", rec.Body.String())
|
||||
}
|
||||
|
||||
c.X().echo.renderer = nil
|
||||
c.Context().echo.renderer = nil
|
||||
err = c.Render(http.StatusOK, "hello", "Joe")
|
||||
assert.Error(t, err)
|
||||
|
||||
@ -226,12 +226,12 @@ func TestContext(t *testing.T) {
|
||||
|
||||
// Error
|
||||
rec = test.NewResponseRecorder()
|
||||
c = NewContext(req, rec, e).X()
|
||||
c = NewContext(req, rec, e).Context()
|
||||
c.Error(errors.New("error"))
|
||||
assert.Equal(t, http.StatusInternalServerError, c.Response().Status())
|
||||
|
||||
// reset
|
||||
c.X().reset(req, test.NewResponseRecorder(), e)
|
||||
c.Context().reset(req, test.NewResponseRecorder(), e)
|
||||
}
|
||||
|
||||
func TestContextPath(t *testing.T) {
|
||||
|
51
echo.go
51
echo.go
@ -554,8 +554,23 @@ func (e *Echo) SetEngine(t engine.Type) {
|
||||
}
|
||||
|
||||
// Run runs a server.
|
||||
func (e *Echo) Run(address string) {
|
||||
config := &engine.Config{Address: address}
|
||||
func (e *Echo) Run(addr string) {
|
||||
c := &engine.Config{Address: addr}
|
||||
e.RunWithConfig(c)
|
||||
}
|
||||
|
||||
// RunTLS runs a server with TLS configuration.
|
||||
func (e *Echo) RunTLS(addr, certfile, keyfile string) {
|
||||
c := &engine.Config{
|
||||
Address: addr,
|
||||
TLSCertfile: certfile,
|
||||
TLSKeyfile: keyfile,
|
||||
}
|
||||
e.RunWithConfig(c)
|
||||
}
|
||||
|
||||
// RunWithConfig runs a server with engine configuration.
|
||||
func (e *Echo) RunWithConfig(config *engine.Config) {
|
||||
handler := func(req engine.Request, res engine.Response) {
|
||||
if e.hook != nil {
|
||||
e.hook(req, res)
|
||||
@ -585,38 +600,6 @@ func (e *Echo) Run(address string) {
|
||||
}
|
||||
|
||||
e.engine.Start()
|
||||
|
||||
// e.run(e.Server(addr))
|
||||
}
|
||||
|
||||
// RunTLS runs a server with TLS configuration.
|
||||
func (e *Echo) RunTLS(addr, crtFile, keyFile string) {
|
||||
// e.run(e.Server(addr), crtFile, keyFile)
|
||||
}
|
||||
|
||||
// RunServer runs a custom server.
|
||||
func (e *Echo) RunServer(s *http.Server) {
|
||||
// e.run(s)
|
||||
}
|
||||
|
||||
// RunTLSServer runs a custom server with TLS configuration.
|
||||
func (e *Echo) RunTLSServer(s *http.Server, crtFile, keyFile string) {
|
||||
// e.run(s, crtFile, keyFile)
|
||||
}
|
||||
|
||||
func (e *Echo) run(s *http.Server, files ...string) {
|
||||
// s.Handler = e
|
||||
// // TODO: Remove in Go 1.6+
|
||||
// if e.http2 {
|
||||
// http2.ConfigureServer(s, nil)
|
||||
// }
|
||||
// if len(files) == 0 {
|
||||
// e.logger.Fatal(s.ListenAndServe())
|
||||
// } else if len(files) == 2 {
|
||||
// e.logger.Fatal(s.ListenAndServeTLS(files[0], files[1]))
|
||||
// } else {
|
||||
// e.logger.Fatal("invalid TLS configuration")
|
||||
// }
|
||||
}
|
||||
|
||||
func NewHTTPError(code int, msg ...string) *HTTPError {
|
||||
|
22
echo_test.go
22
echo_test.go
@ -307,9 +307,9 @@ func TestEchoGroup(t *testing.T) {
|
||||
func TestEchoNotFound(t *testing.T) {
|
||||
e := New()
|
||||
req := test.NewRequest(GET, "/files", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, res)
|
||||
assert.Equal(t, http.StatusNotFound, res.Status())
|
||||
rec := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, rec)
|
||||
assert.Equal(t, http.StatusNotFound, rec.Status())
|
||||
}
|
||||
|
||||
func TestEchoMethodNotAllowed(t *testing.T) {
|
||||
@ -318,9 +318,9 @@ func TestEchoMethodNotAllowed(t *testing.T) {
|
||||
return c.String(http.StatusOK, "Echo!")
|
||||
})
|
||||
req := test.NewRequest(POST, "/", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, res)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, res.Status())
|
||||
rec := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, rec)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, rec.Status())
|
||||
}
|
||||
|
||||
func TestEchoHTTPError(t *testing.T) {
|
||||
@ -349,8 +349,8 @@ func TestEchoHook(t *testing.T) {
|
||||
}
|
||||
})
|
||||
req := test.NewRequest(GET, "/test/", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, res)
|
||||
rec := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, rec)
|
||||
assert.Equal(t, req.URL().Path(), "/test")
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ func testMethod(t *testing.T, method, path string, e *Echo) {
|
||||
|
||||
func request(method, path string, e *Echo) (int, string) {
|
||||
req := test.NewRequest(method, path, nil)
|
||||
res := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, res)
|
||||
return res.Status(), res.Body.String()
|
||||
rec := test.NewResponseRecorder()
|
||||
e.ServeHTTP(req, rec)
|
||||
return rec.Status(), rec.Body.String()
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package engine
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
Type uint8
|
||||
@ -31,6 +34,8 @@ type (
|
||||
Status() int
|
||||
Size() int64
|
||||
Committed() bool
|
||||
SetWriter(io.Writer)
|
||||
Writer() io.Writer
|
||||
}
|
||||
|
||||
Header interface {
|
||||
@ -49,7 +54,11 @@ type (
|
||||
}
|
||||
|
||||
Config struct {
|
||||
Address string
|
||||
Address string
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
TLSCertfile string
|
||||
TLSKeyfile string
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package fasthttp
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/labstack/echo/engine"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
@ -12,6 +14,7 @@ type (
|
||||
status int
|
||||
size int64
|
||||
committed bool
|
||||
writer io.Writer
|
||||
}
|
||||
)
|
||||
|
||||
@ -38,3 +41,11 @@ func (r *Response) Size() int64 {
|
||||
func (r *Response) Committed() bool {
|
||||
return r.committed
|
||||
}
|
||||
|
||||
func (r *Response) SetWriter(w io.Writer) {
|
||||
r.writer = w
|
||||
}
|
||||
|
||||
func (r *Response) Writer() io.Writer {
|
||||
return r.writer
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
package fasthttp
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/gommon/log"
|
||||
)
|
||||
import (
|
||||
"github.com/labstack/echo/engine"
|
||||
@ -27,7 +28,6 @@ func NewServer(config *engine.Config, handler engine.HandlerFunc) *Server {
|
||||
|
||||
func (s *Server) Start() {
|
||||
fasthttp.ListenAndServe(s.config.Address, func(ctx *fasthttp.RequestCtx) {
|
||||
println("FastHTTP")
|
||||
req := &Request{
|
||||
context: ctx,
|
||||
url: &URL{ctx.URI()},
|
||||
|
@ -4,22 +4,26 @@ import "net/http"
|
||||
|
||||
type (
|
||||
Header struct {
|
||||
http.Header
|
||||
header http.Header
|
||||
}
|
||||
)
|
||||
|
||||
func (h *Header) Add(key, val string) {
|
||||
h.Header.Add(key, val)
|
||||
h.header.Add(key, val)
|
||||
}
|
||||
|
||||
func (h *Header) Del(key string) {
|
||||
h.Header.Del(key)
|
||||
h.header.Del(key)
|
||||
}
|
||||
|
||||
func (h *Header) Get(key string) string {
|
||||
return h.Header.Get(key)
|
||||
return h.header.Get(key)
|
||||
}
|
||||
|
||||
func (h *Header) Set(key, val string) {
|
||||
h.Header.Set(key, val)
|
||||
h.header.Set(key, val)
|
||||
}
|
||||
|
||||
func (h *Header) reset(hdr http.Header) {
|
||||
h.header = hdr
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ type (
|
||||
func NewRequest(r *http.Request) *Request {
|
||||
return &Request{
|
||||
request: r,
|
||||
url: NewURL(r.URL),
|
||||
url: &URL{url: r.URL},
|
||||
header: &Header{r.Header},
|
||||
}
|
||||
}
|
||||
@ -54,3 +54,9 @@ func (r *Request) Body() io.ReadCloser {
|
||||
func (r *Request) FormValue(name string) string {
|
||||
return r.request.FormValue(name)
|
||||
}
|
||||
|
||||
func (r *Request) reset(req *http.Request, h engine.Header, u engine.URL) {
|
||||
r.request = req
|
||||
r.header = h
|
||||
r.url = u
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package standard
|
||||
|
||||
import "net/http"
|
||||
import "github.com/labstack/echo/engine"
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/engine"
|
||||
)
|
||||
|
||||
type (
|
||||
Response struct {
|
||||
@ -10,6 +14,7 @@ type (
|
||||
status int
|
||||
size int64
|
||||
committed bool
|
||||
writer io.Writer
|
||||
}
|
||||
)
|
||||
|
||||
@ -17,6 +22,7 @@ func NewResponse(w http.ResponseWriter) *Response {
|
||||
return &Response{
|
||||
response: w,
|
||||
header: &Header{w.Header()},
|
||||
writer: w,
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +41,7 @@ func (r *Response) WriteHeader(code int) {
|
||||
}
|
||||
|
||||
func (r *Response) Write(b []byte) (n int, err error) {
|
||||
n, err = r.response.Write(b)
|
||||
n, err = r.writer.Write(b)
|
||||
r.size += int64(n)
|
||||
return
|
||||
}
|
||||
@ -51,3 +57,20 @@ func (r *Response) Size() int64 {
|
||||
func (r *Response) Committed() bool {
|
||||
return r.committed
|
||||
}
|
||||
|
||||
func (r *Response) SetWriter(w io.Writer) {
|
||||
r.writer = w
|
||||
}
|
||||
|
||||
func (r *Response) Writer() io.Writer {
|
||||
return r.writer
|
||||
}
|
||||
|
||||
func (r *Response) reset(w http.ResponseWriter, h engine.Header) {
|
||||
r.response = w
|
||||
r.header = h
|
||||
r.status = http.StatusOK
|
||||
r.size = 0
|
||||
r.committed = false
|
||||
r.writer = w
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package standard
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/labstack/echo/engine"
|
||||
)
|
||||
@ -12,6 +13,14 @@ type (
|
||||
*http.Server
|
||||
config *engine.Config
|
||||
handler engine.HandlerFunc
|
||||
pool *Pool
|
||||
}
|
||||
|
||||
Pool struct {
|
||||
request sync.Pool
|
||||
response sync.Pool
|
||||
header sync.Pool
|
||||
url sync.Pool
|
||||
}
|
||||
)
|
||||
|
||||
@ -20,13 +29,54 @@ func NewServer(config *engine.Config, handler engine.HandlerFunc) *Server {
|
||||
Server: new(http.Server),
|
||||
config: config,
|
||||
handler: handler,
|
||||
pool: &Pool{
|
||||
request: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Request{}
|
||||
},
|
||||
},
|
||||
response: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Response{}
|
||||
},
|
||||
},
|
||||
header: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Header{}
|
||||
},
|
||||
},
|
||||
url: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &URL{}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) Start() {
|
||||
s.Addr = s.config.Address
|
||||
s.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
s.handler(NewRequest(r), NewResponse(w))
|
||||
// Request
|
||||
req := s.pool.request.Get().(*Request)
|
||||
reqHdr := s.pool.request.Get().(*Header)
|
||||
reqURL := s.pool.request.Get().(*URL)
|
||||
reqHdr.reset(r.Header)
|
||||
reqURL.reset(r.URL)
|
||||
req.reset(r, reqHdr, reqURL)
|
||||
|
||||
// Response
|
||||
res := s.pool.request.Get().(*Response)
|
||||
resHdr := s.pool.request.Get().(*Header)
|
||||
res.reset(w, reqHdr)
|
||||
|
||||
s.handler(req, res)
|
||||
|
||||
s.pool.request.Put(req)
|
||||
s.pool.header.Put(reqHdr)
|
||||
s.pool.url.Put(reqURL)
|
||||
s.pool.response.Put(res)
|
||||
s.pool.header.Put(resHdr)
|
||||
})
|
||||
log.Fatal(s.ListenAndServe())
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func NewURL(u *url.URL) *URL {
|
||||
return &URL{url: u}
|
||||
}
|
||||
|
||||
func (u *URL) URL() *url.URL {
|
||||
return u.url
|
||||
}
|
||||
@ -39,3 +35,7 @@ func (u *URL) QueryValue(name string) string {
|
||||
}
|
||||
return u.query.Get(name)
|
||||
}
|
||||
|
||||
func (u *URL) reset(url *url.URL) {
|
||||
u.url = url
|
||||
}
|
||||
|
@ -1,74 +1,74 @@
|
||||
package middleware
|
||||
|
||||
//
|
||||
// import (
|
||||
// "bufio"
|
||||
// "compress/gzip"
|
||||
// "io"
|
||||
// "io/ioutil"
|
||||
// "net"
|
||||
// "net/http"
|
||||
// "strings"
|
||||
// "sync"
|
||||
//
|
||||
// "github.com/labstack/echo"
|
||||
// )
|
||||
//
|
||||
// type (
|
||||
// gzipWriter struct {
|
||||
// io.Writer
|
||||
// http.ResponseWriter
|
||||
// }
|
||||
// )
|
||||
//
|
||||
// func (w gzipWriter) Write(b []byte) (int, error) {
|
||||
// if w.Header().Get(echo.ContentType) == "" {
|
||||
// w.Header().Set(echo.ContentType, http.DetectContentType(b))
|
||||
// }
|
||||
// return w.Writer.Write(b)
|
||||
// }
|
||||
//
|
||||
// func (w gzipWriter) Flush() error {
|
||||
// return w.Writer.(*gzip.Writer).Flush()
|
||||
// }
|
||||
//
|
||||
// func (w gzipWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
// return w.ResponseWriter.(http.Hijacker).Hijack()
|
||||
// }
|
||||
//
|
||||
// func (w *gzipWriter) CloseNotify() <-chan bool {
|
||||
// return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
|
||||
// }
|
||||
//
|
||||
// var writerPool = sync.Pool{
|
||||
// New: func() interface{} {
|
||||
// return gzip.NewWriter(ioutil.Discard)
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // Gzip returns a middleware which compresses HTTP response using gzip compression
|
||||
// // scheme.
|
||||
// func Gzip() echo.MiddlewareFunc {
|
||||
// scheme := "gzip"
|
||||
//
|
||||
// return func(h echo.HandlerFunc) echo.HandlerFunc {
|
||||
// return func(c echo.Context) error {
|
||||
// c.Response().Header().Add(echo.Vary, echo.AcceptEncoding)
|
||||
// if strings.Contains(c.Request().Header().Get(echo.AcceptEncoding), scheme) {
|
||||
// w := writerPool.Get().(*gzip.Writer)
|
||||
// w.Reset(c.Response().Writer())
|
||||
// defer func() {
|
||||
// w.Close()
|
||||
// writerPool.Put(w)
|
||||
// }()
|
||||
// gw := gzipWriter{Writer: w, ResponseWriter: c.Response().Writer()}
|
||||
// c.Response().Header().Set(echo.ContentEncoding, scheme)
|
||||
// c.Response().SetWriter(gw)
|
||||
// }
|
||||
// if err := h(c); err != nil {
|
||||
// c.Error(err)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
import (
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/engine"
|
||||
)
|
||||
|
||||
type (
|
||||
gzipWriter struct {
|
||||
io.Writer
|
||||
engine.Response
|
||||
}
|
||||
)
|
||||
|
||||
func (w gzipWriter) Write(b []byte) (int, error) {
|
||||
if w.Header().Get(echo.ContentType) == "" {
|
||||
w.Header().Set(echo.ContentType, http.DetectContentType(b))
|
||||
}
|
||||
return w.Writer.Write(b)
|
||||
}
|
||||
|
||||
func (w gzipWriter) Flush() error {
|
||||
return w.Writer.(*gzip.Writer).Flush()
|
||||
}
|
||||
|
||||
func (w gzipWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
return w.Response.(http.Hijacker).Hijack()
|
||||
}
|
||||
|
||||
func (w *gzipWriter) CloseNotify() <-chan bool {
|
||||
return w.Response.(http.CloseNotifier).CloseNotify()
|
||||
}
|
||||
|
||||
var writerPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return gzip.NewWriter(ioutil.Discard)
|
||||
},
|
||||
}
|
||||
|
||||
// Gzip returns a middleware which compresses HTTP response using gzip compression
|
||||
// scheme.
|
||||
func Gzip() echo.MiddlewareFunc {
|
||||
scheme := "gzip"
|
||||
|
||||
return func(h echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
c.Response().Header().Add(echo.Vary, echo.AcceptEncoding)
|
||||
if strings.Contains(c.Request().Header().Get(echo.AcceptEncoding), scheme) {
|
||||
w := writerPool.Get().(*gzip.Writer)
|
||||
w.Reset(c.Response().Writer())
|
||||
defer func() {
|
||||
w.Close()
|
||||
writerPool.Put(w)
|
||||
}()
|
||||
gw := gzipWriter{Writer: w, Response: c.Response()}
|
||||
c.Response().Header().Set(echo.ContentEncoding, scheme)
|
||||
c.Response().SetWriter(gw)
|
||||
}
|
||||
if err := h(c); err != nil {
|
||||
c.Error(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +1,69 @@
|
||||
package middleware
|
||||
|
||||
//
|
||||
// import (
|
||||
// "bytes"
|
||||
// "compress/gzip"
|
||||
// "net/http"
|
||||
// "net/http/httptest"
|
||||
// "testing"
|
||||
// "time"
|
||||
//
|
||||
// "github.com/labstack/echo"
|
||||
// "github.com/labstack/echo/test"
|
||||
// "github.com/stretchr/testify/assert"
|
||||
// )
|
||||
//
|
||||
// type closeNotifyingRecorder struct {
|
||||
// *httptest.ResponseRecorder
|
||||
// closed chan bool
|
||||
// }
|
||||
//
|
||||
// func newCloseNotifyingRecorder() *closeNotifyingRecorder {
|
||||
// return &closeNotifyingRecorder{
|
||||
// test.NewResponseRecorder(),
|
||||
// make(chan bool, 1),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func (c *closeNotifyingRecorder) close() {
|
||||
// c.closed <- true
|
||||
// }
|
||||
//
|
||||
// func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
|
||||
// return c.closed
|
||||
// }
|
||||
//
|
||||
// func TestGzip(t *testing.T) {
|
||||
// e := echo.New()
|
||||
// req := test.NewRequest(echo.GET, "/", nil)
|
||||
// res := test.NewResponseRecorder()
|
||||
// c := echo.NewContext(req, res, e)
|
||||
// h := func(c echo.Context) error {
|
||||
// c.Response().Write([]byte("test")) // For Content-Type sniffing
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// // Skip if no Accept-Encoding header
|
||||
// Gzip()(h)(c)
|
||||
// assert.Equal(t, http.StatusOK, res.Status())
|
||||
// assert.Equal(t, "test", res.Body().String())
|
||||
//
|
||||
// req = test.NewRequest(echo.GET, "/", nil)
|
||||
// req.Header.Set(echo.AcceptEncoding, "gzip")
|
||||
// res = test.NewResponseRecorder()
|
||||
// c = echo.NewContext(req, res, e)
|
||||
//
|
||||
// // Gzip
|
||||
// Gzip()(h)(c)
|
||||
// assert.Equal(t, http.StatusOK, res.Status())
|
||||
// assert.Equal(t, "gzip", res.Header().Get(echo.ContentEncoding))
|
||||
// assert.Contains(t, res.Header().Get(echo.ContentType), echo.TextPlain)
|
||||
// r, err := gzip.NewReader(res.Body())
|
||||
// defer r.Close()
|
||||
// if assert.NoError(t, err) {
|
||||
// buf := new(bytes.Buffer)
|
||||
// buf.ReadFrom(r)
|
||||
// assert.Equal(t, "test", buf.String())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"testing"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/test"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type closeNotifyingRecorder struct {
|
||||
*test.ResponseRecorder
|
||||
closed chan bool
|
||||
}
|
||||
|
||||
func newCloseNotifyingRecorder() *closeNotifyingRecorder {
|
||||
return &closeNotifyingRecorder{
|
||||
test.NewResponseRecorder(),
|
||||
make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *closeNotifyingRecorder) close() {
|
||||
c.closed <- true
|
||||
}
|
||||
|
||||
func (c *closeNotifyingRecorder) CloseNotify() <-chan bool {
|
||||
return c.closed
|
||||
}
|
||||
|
||||
func TestGzip(t *testing.T) {
|
||||
e := echo.New()
|
||||
req := test.NewRequest(echo.GET, "/", nil)
|
||||
rec := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, rec, e)
|
||||
h := func(c echo.Context) error {
|
||||
c.Response().Write([]byte("test")) // For Content-Type sniffing
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip if no Accept-Encoding header
|
||||
Gzip()(h)(c)
|
||||
// assert.Equal(t, http.StatusOK, rec.Status())
|
||||
assert.Equal(t, "test", rec.Body.String())
|
||||
|
||||
req = test.NewRequest(echo.GET, "/", nil)
|
||||
req.Header().Set(echo.AcceptEncoding, "gzip")
|
||||
rec = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, rec, e)
|
||||
|
||||
// Gzip
|
||||
Gzip()(h)(c)
|
||||
// assert.Equal(t, http.StatusOK, rec.Status())
|
||||
assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding))
|
||||
assert.Contains(t, rec.Header().Get(echo.ContentType), echo.TextPlain)
|
||||
r, err := gzip.NewReader(rec.Body)
|
||||
defer r.Close()
|
||||
if assert.NoError(t, err) {
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(r)
|
||||
assert.Equal(t, "test", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
// func TestGzipFlush(t *testing.T) {
|
||||
// res := test.NewResponseRecorder()
|
||||
// buf := new(bytes.Buffer)
|
||||
@ -104,7 +100,7 @@ package middleware
|
||||
// t.Fatal("Flush didn't flush any data")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
// func TestGzipCloseNotify(t *testing.T) {
|
||||
// rec := newCloseNotifyingRecorder()
|
||||
// buf := new(bytes.Buffer)
|
||||
|
@ -15,8 +15,8 @@ func TestLogger(t *testing.T) {
|
||||
// Note: Just for the test coverage, not a real test.
|
||||
e := echo.New()
|
||||
req := test.NewRequest(echo.GET, "/", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, res, e)
|
||||
rec := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, rec, e)
|
||||
|
||||
// Status 2xx
|
||||
h := func(c echo.Context) error {
|
||||
@ -25,16 +25,16 @@ func TestLogger(t *testing.T) {
|
||||
Logger()(h)(c)
|
||||
|
||||
// Status 3xx
|
||||
res = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, res, e)
|
||||
rec = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, rec, e)
|
||||
h = func(c echo.Context) error {
|
||||
return c.String(http.StatusTemporaryRedirect, "test")
|
||||
}
|
||||
Logger()(h)(c)
|
||||
|
||||
// Status 4xx
|
||||
res = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, res, e)
|
||||
rec = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, rec, e)
|
||||
h = func(c echo.Context) error {
|
||||
return c.String(http.StatusNotFound, "test")
|
||||
}
|
||||
@ -42,8 +42,8 @@ func TestLogger(t *testing.T) {
|
||||
|
||||
// Status 5xx with empty path
|
||||
req = test.NewRequest(echo.GET, "", nil)
|
||||
res = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, res, e)
|
||||
rec = test.NewResponseRecorder()
|
||||
c = echo.NewContext(req, rec, e)
|
||||
h = func(c echo.Context) error {
|
||||
return errors.New("error")
|
||||
}
|
||||
@ -53,8 +53,8 @@ func TestLogger(t *testing.T) {
|
||||
func TestLoggerIPAddress(t *testing.T) {
|
||||
e := echo.New()
|
||||
req := test.NewRequest(echo.GET, "/", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, res, e)
|
||||
rec := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, rec, e)
|
||||
buf := new(bytes.Buffer)
|
||||
e.Logger().SetOutput(buf)
|
||||
ip := "127.0.0.1"
|
||||
|
@ -13,12 +13,12 @@ func TestRecover(t *testing.T) {
|
||||
e := echo.New()
|
||||
e.SetDebug(true)
|
||||
req := test.NewRequest(echo.GET, "/", nil)
|
||||
res := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, res, e)
|
||||
rec := test.NewResponseRecorder()
|
||||
c := echo.NewContext(req, rec, e)
|
||||
h := func(c echo.Context) error {
|
||||
panic("test")
|
||||
}
|
||||
Recover()(h)(c)
|
||||
assert.Equal(t, http.StatusInternalServerError, res.Status())
|
||||
assert.Contains(t, res.Body.String(), "panic recover")
|
||||
assert.Equal(t, http.StatusInternalServerError, rec.Status())
|
||||
assert.Contains(t, rec.Body.String(), "panic recover")
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ func (n *node) check405() HandlerFunc {
|
||||
}
|
||||
|
||||
func (r *Router) Find(method, path string, context Context) (h HandlerFunc, e *Echo) {
|
||||
x := context.X()
|
||||
x := context.Context()
|
||||
h = notFoundHandler
|
||||
e = r.echo
|
||||
cn := r.tree // Current node as root
|
||||
|
@ -529,16 +529,16 @@ func TestRouterParamNames(t *testing.T) {
|
||||
// Route > /users/:id
|
||||
h, _ = r.Find(GET, "/users/1", c)
|
||||
if assert.NotNil(t, h) {
|
||||
assert.Equal(t, "id", c.X().pnames[0])
|
||||
assert.Equal(t, "id", c.Context().pnames[0])
|
||||
assert.Equal(t, "1", c.P(0))
|
||||
}
|
||||
|
||||
// Route > /users/:uid/files/:fid
|
||||
h, _ = r.Find(GET, "/users/1/files/1", c)
|
||||
if assert.NotNil(t, h) {
|
||||
assert.Equal(t, "uid", c.X().pnames[0])
|
||||
assert.Equal(t, "uid", c.Context().pnames[0])
|
||||
assert.Equal(t, "1", c.P(0))
|
||||
assert.Equal(t, "fid", c.X().pnames[1])
|
||||
assert.Equal(t, "fid", c.Context().pnames[1])
|
||||
assert.Equal(t, "1", c.P(1))
|
||||
}
|
||||
}
|
||||
@ -556,7 +556,7 @@ func TestRouterAPI(t *testing.T) {
|
||||
for _, route := range api {
|
||||
h, _ := r.Find(route.Method, route.Path, c)
|
||||
if assert.NotNil(t, h) {
|
||||
for i, n := range c.X().pnames {
|
||||
for i, n := range c.Context().pnames {
|
||||
if assert.NotEmpty(t, n) {
|
||||
assert.Equal(t, ":"+n, c.P(i))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user