1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-24 08:22:21 +02:00
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2016-03-27 16:29:41 -07:00
parent d3e33ec4dd
commit a2d757eddc
4 changed files with 51 additions and 11 deletions

View File

@ -7,7 +7,6 @@ import (
"mime"
"mime/multipart"
"net/http"
"os"
"path"
"path/filepath"
"time"
@ -134,6 +133,11 @@ 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(http.File) error
// Object returns the `context` instance.
Object() *context
@ -376,10 +380,8 @@ func (c *context) File(file string) error {
if err != nil {
return ErrNotFound
}
fi, _ = f.Stat()
}
return ServeContent(c.Request(), c.Response(), f, fi)
return c.ServeContent(f)
}
func (c *context) Attachment(r io.Reader, name string) (err error) {
@ -420,13 +422,24 @@ func (c *context) Object() *context {
return c
}
// ServeContent sends a response from `io.Reader`. It automatically sets the `Content-Type`
// and `Last-Modified` headers.
func ServeContent(rq engine.Request, rs engine.Response, f http.File, fi os.FileInfo) error {
func (c *context) ServeContent(f http.File) error {
rq := c.Request()
rs := c.Response()
fi, err := f.Stat()
if err != nil {
return err
}
if t, err := time.Parse(http.TimeFormat, rq.Header().Get(IfModifiedSince)); err == nil && fi.ModTime().Before(t.Add(1*time.Second)) {
rs.Header().Del(ContentType)
rs.Header().Del(ContentLength)
return c.NoContent(http.StatusNotModified)
}
rs.Header().Set(ContentType, detectContentType(fi.Name()))
rs.Header().Set(LastModified, fi.ModTime().UTC().Format(http.TimeFormat))
rs.WriteHeader(http.StatusOK)
_, err := io.Copy(rs, f)
_, err = io.Copy(rs, f)
return err
}

View File

@ -239,6 +239,33 @@ func TestContextNetContext(t *testing.T) {
// assert.Equal(t, "val", c.Value("key"))
}
func TestContextServeContent(t *testing.T) {
e := New()
rq := test.NewRequest(GET, "/", nil)
rc := test.NewResponseRecorder()
c := NewContext(rq, rc, e)
// Not cached
fs := http.Dir("_fixture/images")
f, err := fs.Open("walle.png")
if assert.NoError(t, err) {
if assert.NoError(t, c.ServeContent(f)) {
assert.Equal(t, http.StatusOK, rc.Status())
}
}
// Cached
rc = test.NewResponseRecorder()
c = NewContext(rq, rc, e)
fi, err := f.Stat()
if assert.NoError(t, err) {
rq.Header().Set(IfModifiedSince, fi.ModTime().UTC().Format(http.TimeFormat))
if assert.NoError(t, c.ServeContent(f)) {
assert.Equal(t, http.StatusNotModified, rc.Status())
}
}
}
func testBindOk(t *testing.T, c Context, ct string) {
c.Request().Header().Set(ContentType, ct)
u := new(user)

View File

@ -176,6 +176,7 @@ const (
ContentEncoding = "Content-Encoding"
ContentLength = "Content-Length"
ContentType = "Content-Type"
IfModifiedSince = "If-Modified-Since"
LastModified = "Last-Modified"
Location = "Location"
Upgrade = "Upgrade"

View File

@ -61,7 +61,7 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
if fi.IsDir() {
/* NOTE:
Not checking the Last-Modified header as it caches the response `304` when
changing differnt directories for the same path.
changing different directories for the same path.
*/
d := f
@ -97,9 +97,8 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
}
return next.Handle(c)
}
fi, _ = f.Stat() // Index file stat
}
return echo.ServeContent(c.Request(), c.Response(), f, fi)
return c.ServeContent(f)
})
}
}