diff --git a/README.md b/README.md index 792cd1f7..32d8d1b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + [![Sourcegraph](https://sourcegraph.com/github.com/labstack/echo/-/badge.svg?style=flat-square)](https://sourcegraph.com/github.com/labstack/echo?badge) [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/labstack/echo) diff --git a/echo.go b/echo.go index ed41357b..94e2ab10 100644 --- a/echo.go +++ b/echo.go @@ -72,6 +72,7 @@ type ( TLSServer *http.Server Listener net.Listener TLSListener net.Listener + AutoTLSManager autocert.Manager DisableHTTP2 bool Debug bool HideBanner bool @@ -79,7 +80,6 @@ type ( Binder Binder Validator Validator Renderer Renderer - AutoTLSManager autocert.Manager // Mutex sync.RWMutex Logger Logger } @@ -293,14 +293,16 @@ func New() (e *Echo) { // NewContext returns a Context instance. func (e *Echo) NewContext(r *http.Request, w http.ResponseWriter) Context { - return &context{ + c := &context{ request: r, - response: NewResponse(w, e), + response: &Response{Writer: w}, store: make(Map), echo: e, pvalues: make([]string, *e.maxParam), handler: NotFoundHandler, } + c.response.context = c + return c } // Router returns router. diff --git a/response.go b/response.go index 2c70d213..ae262f24 100644 --- a/response.go +++ b/response.go @@ -11,18 +11,18 @@ type ( // by an HTTP handler to construct an HTTP response. // See: https://golang.org/pkg/net/http/#ResponseWriter Response struct { - Writer http.ResponseWriter - Status int - Size int64 - Committed bool - echo *Echo + context Context + beforeFuncs []BeforeResponseFunc + Writer http.ResponseWriter + Status int + Size int64 + Committed bool } -) -// NewResponse creates a new instance of Response. -func NewResponse(w http.ResponseWriter, e *Echo) (r *Response) { - return &Response{Writer: w, echo: e} -} + // BeforeResponseFunc defines a function which is called just before writing the + // response. + BeforeResponseFunc func(Context) +) // Header returns the header map for the writer that will be sent by // WriteHeader. Changing the header after a call to WriteHeader (or Write) has @@ -34,15 +34,23 @@ func (r *Response) Header() http.Header { return r.Writer.Header() } +// Before registers a function which is called just before the response is written. +func (r *Response) Before(fn BeforeResponseFunc) { + r.beforeFuncs = append(r.beforeFuncs, fn) +} + // WriteHeader sends an HTTP response header with status code. If WriteHeader is // not called explicitly, the first call to Write will trigger an implicit // WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly // used to send error codes. func (r *Response) WriteHeader(code int) { if r.Committed { - r.echo.Logger.Warn("response already committed") + r.context.Logger().Warn("response already committed") return } + // for _, fn := range r.beforeFuncs { + // fn(r.context) + // } r.Status = code r.Writer.WriteHeader(code) r.Committed = true diff --git a/response_test.go b/response_test.go new file mode 100644 index 00000000..95fb3227 --- /dev/null +++ b/response_test.go @@ -0,0 +1,23 @@ +package echo + +import ( + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestResponse(t *testing.T) { + e := New() + req := httptest.NewRequest(GET, "/", nil) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + res := &Response{context: c, Writer: rec} + + // Before + res.Before(func(c Context) { + c.Response().Header().Set(HeaderServer, "echo") + }) + res.Write([]byte("test")) + assert.Equal(t, "echo", rec.Header().Get(HeaderServer)) +}