mirror of https://github.com/go-gitea/gitea.git
Add ETag header to avatars (#721)
This commit is contained in:
parent
8093b3372e
commit
8555e888d8
|
@ -99,6 +99,7 @@ func newMacaron() *macaron.Macaron {
|
||||||
macaron.StaticOptions{
|
macaron.StaticOptions{
|
||||||
Prefix: "avatars",
|
Prefix: "avatars",
|
||||||
SkipLogging: setting.DisableRouterLog,
|
SkipLogging: setting.DisableRouterLog,
|
||||||
|
ETag: true,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,16 @@
|
||||||
package bindata
|
package bindata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/elazarl/go-bindata-assetfs"
|
"github.com/elazarl/go-bindata-assetfs"
|
||||||
"gopkg.in/macaron.v1"
|
"gopkg.in/macaron.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const _VERSION = "0.1.0"
|
const _VERSION = "0.1.1"
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return _VERSION
|
return _VERSION
|
||||||
|
@ -69,6 +72,15 @@ func (templates templateFileSystem) ListFiles() []macaron.TemplateFile {
|
||||||
return templates.files
|
return templates.files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (templates templateFileSystem) Get(name string) (io.Reader, error) {
|
||||||
|
for i := range templates.files {
|
||||||
|
if templates.files[i].Name()+templates.files[i].Ext() == name {
|
||||||
|
return bytes.NewReader(templates.files[i].Data()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("file '%s' not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *templateFile) Name() string {
|
func (f *templateFile) Name() string {
|
||||||
return f.name
|
return f.name
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import (
|
||||||
"github.com/go-macaron/inject"
|
"github.com/go-macaron/inject"
|
||||||
)
|
)
|
||||||
|
|
||||||
const _VERSION = "1.1.8.0826"
|
const _VERSION = "1.1.12.0122"
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
return _VERSION
|
return _VERSION
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -72,6 +73,7 @@ type (
|
||||||
// TemplateFileSystem represents a interface of template file system that able to list all files.
|
// TemplateFileSystem represents a interface of template file system that able to list all files.
|
||||||
TemplateFileSystem interface {
|
TemplateFileSystem interface {
|
||||||
ListFiles() []TemplateFile
|
ListFiles() []TemplateFile
|
||||||
|
Get(string) (io.Reader, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delims represents a set of Left and Right delimiters for HTML template rendering
|
// Delims represents a set of Left and Right delimiters for HTML template rendering
|
||||||
|
@ -246,6 +248,15 @@ func (fs TplFileSystem) ListFiles() []TemplateFile {
|
||||||
return fs.files
|
return fs.files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fs TplFileSystem) Get(name string) (io.Reader, error) {
|
||||||
|
for i := range fs.files {
|
||||||
|
if fs.files[i].Name()+fs.files[i].Ext() == name {
|
||||||
|
return bytes.NewReader(fs.files[i].Data()), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("file '%s' not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
func PrepareCharset(charset string) string {
|
func PrepareCharset(charset string) string {
|
||||||
if len(charset) != 0 {
|
if len(charset) != 0 {
|
||||||
return "; charset=" + charset
|
return "; charset=" + charset
|
||||||
|
|
|
@ -258,7 +258,9 @@ func (r *Router) NotFound(handlers ...Handler) {
|
||||||
validateHandlers(handlers)
|
validateHandlers(handlers)
|
||||||
r.notFound = func(rw http.ResponseWriter, req *http.Request) {
|
r.notFound = func(rw http.ResponseWriter, req *http.Request) {
|
||||||
c := r.m.createContext(rw, req)
|
c := r.m.createContext(rw, req)
|
||||||
c.handlers = append(r.m.handlers, handlers...)
|
c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
|
||||||
|
c.handlers = append(c.handlers, r.m.handlers...)
|
||||||
|
c.handlers = append(c.handlers, handlers...)
|
||||||
c.run()
|
c.run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package macaron
|
package macaron
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
@ -35,6 +36,9 @@ type StaticOptions struct {
|
||||||
// Expires defines which user-defined function to use for producing a HTTP Expires Header
|
// Expires defines which user-defined function to use for producing a HTTP Expires Header
|
||||||
// https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
|
// https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
|
||||||
Expires func() string
|
Expires func() string
|
||||||
|
// ETag defines if we should add an ETag header
|
||||||
|
// https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#validating-cached-responses-with-etags
|
||||||
|
ETag bool
|
||||||
// FileSystem is the interface for supporting any implmentation of file system.
|
// FileSystem is the interface for supporting any implmentation of file system.
|
||||||
FileSystem http.FileSystem
|
FileSystem http.FileSystem
|
||||||
}
|
}
|
||||||
|
@ -172,10 +176,21 @@ func staticHandler(ctx *Context, log *log.Logger, opt StaticOptions) bool {
|
||||||
ctx.Resp.Header().Set("Expires", opt.Expires())
|
ctx.Resp.Header().Set("Expires", opt.Expires())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opt.ETag {
|
||||||
|
tag := GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat))
|
||||||
|
ctx.Resp.Header().Set("ETag", tag)
|
||||||
|
}
|
||||||
|
|
||||||
http.ServeContent(ctx.Resp, ctx.Req.Request, file, fi.ModTime(), f)
|
http.ServeContent(ctx.Resp, ctx.Req.Request, file, fi.ModTime(), f)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateETag generates an ETag based on size, filename and file modification time
|
||||||
|
func GenerateETag(fileSize, fileName, modTime string) string {
|
||||||
|
etag := fileSize + fileName + modTime
|
||||||
|
return base64.StdEncoding.EncodeToString([]byte(etag))
|
||||||
|
}
|
||||||
|
|
||||||
// Static returns a middleware handler that serves static files in the given directory.
|
// Static returns a middleware handler that serves static files in the given directory.
|
||||||
func Static(directory string, staticOpt ...StaticOptions) Handler {
|
func Static(directory string, staticOpt ...StaticOptions) Handler {
|
||||||
opt := prepareStaticOptions(directory, staticOpt)
|
opt := prepareStaticOptions(directory, staticOpt)
|
||||||
|
|
|
@ -353,10 +353,10 @@
|
||||||
"revisionTime": "2015-10-06T22:16:25Z"
|
"revisionTime": "2015-10-06T22:16:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "qTJizMr1DBhDTZiRNmC+khEClz8=",
|
"checksumSHA1": "3w6jybRjyrhohNQJMnIxMC8cYXM=",
|
||||||
"path": "github.com/go-macaron/bindata",
|
"path": "github.com/go-macaron/bindata",
|
||||||
"revision": "de74a053830c7d338bf209adf3b711c969f63e59",
|
"revision": "85786f57eee3e5544a9cc24fa2afe425b97a8652",
|
||||||
"revisionTime": "2016-01-05T04:39:20Z"
|
"revisionTime": "2016-12-22T09:30:48Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "qM/kf31cT2cxjtHxdzbu8q8jPq0=",
|
"checksumSHA1": "qM/kf31cT2cxjtHxdzbu8q8jPq0=",
|
||||||
|
@ -1369,10 +1369,10 @@
|
||||||
"revisionTime": "2016-08-08T14:54:09Z"
|
"revisionTime": "2016-08-08T14:54:09Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "wzuoHPA/Ccoe1CFnDL35rnL0JoI=",
|
"checksumSHA1": "u1dW5zfo2SWot04r5cL8dTbmtcc=",
|
||||||
"path": "gopkg.in/macaron.v1",
|
"path": "gopkg.in/macaron.v1",
|
||||||
"revision": "4974334b10dbb6f5c0e17f4c10555ff050a16329",
|
"revision": "aa6b7ee41a182898a33d798c655df1cac9d2230b",
|
||||||
"revisionTime": "2016-08-26T18:07:28Z"
|
"revisionTime": "2017-01-22T14:42:53Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "6QPjE+qflEBHg+JPJd9e4iQuRAk=",
|
"checksumSHA1": "6QPjE+qflEBHg+JPJd9e4iQuRAk=",
|
||||||
|
|
Loading…
Reference in New Issue