From a739d9a0d93734930cd5feb91655e740ad605a98 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 25 Oct 2016 14:53:17 -0700 Subject: [PATCH] - Removed Context#ServeContent - Refactored Context#Attachment, Context#Inline, Context#ContentTypeByExtension Signed-off-by: Vishal Rana --- context.go | 62 +++++++++++-------------------------------------- context_test.go | 50 +++++++-------------------------------- glide.lock | 10 ++++---- 3 files changed, 26 insertions(+), 96 deletions(-) diff --git a/context.go b/context.go index 49bb392b..7f3ddc06 100644 --- a/context.go +++ b/context.go @@ -6,7 +6,6 @@ import ( "encoding/xml" "fmt" "io" - "mime" "mime/multipart" "net" "net/http" @@ -14,7 +13,6 @@ import ( "os" "path/filepath" "strings" - "time" "golang.org/x/net/websocket" ) @@ -142,13 +140,12 @@ type ( // File sends a response with the content of the file. File(string) error - // Attachment sends a response from `io.ReaderSeeker` as attachment, prompting - // client to save the file. - Attachment(io.ReadSeeker, string) error + // Attachment sends a response as attachment, prompting client to save the + // file. + Attachment(string, string) error - // Inline sends a response from `io.ReaderSeeker` as inline, opening - // the file in the browser. - Inline(io.ReadSeeker, string) error + // Inline sends a response as inline, opening the file in the browser. + Inline(string, string) error // NoContent sends a response with no body and a status code. NoContent(int) error @@ -171,11 +168,6 @@ type ( // Echo returns the `Echo` instance. Echo() *Echo - // ServeContent sends static content from `io.Reader` and handles caching - // via `If-Modified-Since` request header. It automatically sets `Content-Type` - // and `Last-Modified` response headers. - ServeContent(io.ReadSeeker, string, time.Time) error - // Reset resets the context after request completes. It must be called along // with `Echo#AcquireContext()` and `Echo#ReleaseContext()`. // See `Echo#ServeHTTP()` @@ -462,22 +454,21 @@ func (c *context) File(file string) error { return err } } - return c.ServeContent(f, fi.Name(), fi.ModTime()) + http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f) + return nil } -func (c *context) Attachment(r io.ReadSeeker, name string) (err error) { - return c.contentDisposition(r, name, "attachment") +func (c *context) Attachment(file, name string) (err error) { + return c.contentDisposition(file, name, "attachment") } -func (c *context) Inline(r io.ReadSeeker, name string) (err error) { - return c.contentDisposition(r, name, "inline") +func (c *context) Inline(file, name string) (err error) { + return c.contentDisposition(file, name, "inline") } -func (c *context) contentDisposition(r io.ReadSeeker, name, dispositionType string) (err error) { - c.response.Header().Set(HeaderContentType, ContentTypeByExtension(name)) +func (c *context) contentDisposition(file, name, dispositionType string) (err error) { c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%s", dispositionType, name)) - c.response.WriteHeader(http.StatusOK) - _, err = io.Copy(c.response, r) + c.File(file) return } @@ -515,33 +506,6 @@ func (c *context) Logger() Logger { return c.echo.Logger } -func (c *context) ServeContent(content io.ReadSeeker, name string, modtime time.Time) error { - req := c.Request() - res := c.Response() - - if t, err := time.Parse(http.TimeFormat, req.Header.Get(HeaderIfModifiedSince)); err == nil && modtime.Before(t.Add(1*time.Second)) { - res.Header().Del(HeaderContentType) - res.Header().Del(HeaderContentLength) - return c.NoContent(http.StatusNotModified) - } - - res.Header().Set(HeaderContentType, ContentTypeByExtension(name)) - res.Header().Set(HeaderLastModified, modtime.UTC().Format(http.TimeFormat)) - res.WriteHeader(http.StatusOK) - _, err := io.Copy(res, content) - return err -} - -// ContentTypeByExtension returns the MIME type associated with the file based on -// its extension. It returns `application/octet-stream` incase MIME type is not -// found. -func ContentTypeByExtension(name string) (t string) { - if t = mime.TypeByExtension(filepath.Ext(name)); t == "" { - t = MIMEOctetStream - } - return -} - func (c *context) Reset(r *http.Request, w http.ResponseWriter) { c.query = nil c.store = nil diff --git a/context_test.go b/context_test.go index d81796f1..6993d610 100644 --- a/context_test.go +++ b/context_test.go @@ -7,7 +7,6 @@ import ( "mime/multipart" "net/http" "net/http/httptest" - "os" "testing" "text/template" "time" @@ -141,27 +140,21 @@ func TestContext(t *testing.T) { // Attachment rec = httptest.NewRecorder() c = e.NewContext(req, rec).(*context) - file, err := os.Open("_fixture/images/walle.png") + err = c.Attachment("_fixture/images/walle.png", "walle.png") if assert.NoError(t, err) { - err = c.Attachment(file, "walle.png") - if assert.NoError(t, err) { - assert.Equal(t, http.StatusOK, rec.Code) - assert.Equal(t, "attachment; filename=walle.png", rec.Header().Get(HeaderContentDisposition)) - assert.Equal(t, 219885, rec.Body.Len()) - } + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, "attachment; filename=walle.png", rec.Header().Get(HeaderContentDisposition)) + assert.Equal(t, 219885, rec.Body.Len()) } // Inline rec = httptest.NewRecorder() c = e.NewContext(req, rec).(*context) - file, err = os.Open("_fixture/images/walle.png") + err = c.Inline("_fixture/images/walle.png", "walle.png") if assert.NoError(t, err) { - err = c.Inline(file, "walle.png") - if assert.NoError(t, err) { - assert.Equal(t, http.StatusOK, rec.Code) - assert.Equal(t, "inline; filename=walle.png", rec.Header().Get(HeaderContentDisposition)) - assert.Equal(t, 219885, rec.Body.Len()) - } + assert.Equal(t, http.StatusOK, rec.Code) + assert.Equal(t, "inline; filename=walle.png", rec.Header().Get(HeaderContentDisposition)) + assert.Equal(t, 219885, rec.Body.Len()) } // NoContent @@ -353,33 +346,6 @@ func TestContextStore(t *testing.T) { assert.Equal(t, "Jon Snow", c.Get("name")) } -func TestContextServeContent(t *testing.T) { - e := New() - req, _ := http.NewRequest(GET, "/", nil) - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - - fs := http.Dir("_fixture/images") - f, err := fs.Open("walle.png") - if assert.NoError(t, err) { - fi, err := f.Stat() - if assert.NoError(t, err) { - // Not cached - if assert.NoError(t, c.ServeContent(f, fi.Name(), fi.ModTime())) { - assert.Equal(t, http.StatusOK, rec.Code) - } - - // Cached - rec = httptest.NewRecorder() - c = e.NewContext(req, rec) - req.Header.Set(HeaderIfModifiedSince, fi.ModTime().UTC().Format(http.TimeFormat)) - if assert.NoError(t, c.ServeContent(f, fi.Name(), fi.ModTime())) { - assert.Equal(t, http.StatusNotModified, rec.Code) - } - } - } -} - func TestContextHandler(t *testing.T) { e := New() r := e.Router() diff --git a/glide.lock b/glide.lock index 3d2bb4cb..cc6709a7 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: b592629b56c43e0f6fcef629a3e46106b07431120d42ed45952d841655407e3e -updated: 2016-10-23T13:10:42.580474947-07:00 +updated: 2016-10-25T11:15:52.451088614-07:00 imports: - name: github.com/daaku/go.zipexe version: a5fe2436ffcb3236e175e5149162b41cd28bd27d @@ -37,15 +37,15 @@ imports: - name: github.com/valyala/fasttemplate version: 3b874956e03f1636d171bda64b130f9135f42cff - name: github.com/xenolf/lego - version: e953bbc8b95ad7d2f7172ae6732e71069be48957 + version: 4bb8bea031eb805f361c04ca222f266b9e7feced subpackages: - acme - name: golang.org/x/crypto - version: 3c0d69f1777220f1a1d2ec373cb94a282f03eb42 + version: ca7e7f10cb9fd9c1a6ff7f60436c086d73714180 subpackages: - ocsp - name: golang.org/x/net - version: c33d37840d93fc75251f49ab83c5fc8b2faea5e8 + version: 65dfc08770ce66f74becfdff5f8ab01caef4e946 subpackages: - context - publicsuffix @@ -79,7 +79,7 @@ testImports: subpackages: - spew - name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + version: 792786c7400a136282c1664665ae0a8db921c6c2 subpackages: - difflib - name: github.com/stretchr/testify