mirror of
https://github.com/caddyserver/caddy.git
synced 2026-05-24 08:26:58 -04:00
Merge pull request #1613 from tw4452852/addlink
Context: add Push action
This commit is contained in:
@@ -29,6 +29,20 @@ type Context struct {
|
||||
Req *http.Request
|
||||
URL *url.URL
|
||||
Args []interface{} // defined by arguments to .Include
|
||||
|
||||
// just used for adding preload links for server push
|
||||
responseHeader http.Header
|
||||
}
|
||||
|
||||
// NewContextWithHeader creates a context with given response header.
|
||||
//
|
||||
// To plugin developer:
|
||||
// The returned context's exported fileds remain empty,
|
||||
// you should then initialize them if you want.
|
||||
func NewContextWithHeader(rh http.Header) Context {
|
||||
return Context{
|
||||
responseHeader: rh,
|
||||
}
|
||||
}
|
||||
|
||||
// Include returns the contents of filename relative to the site root.
|
||||
@@ -410,6 +424,15 @@ func (c Context) RandomString(minLen, maxLen int) string {
|
||||
return string(result)
|
||||
}
|
||||
|
||||
// Push adds a preload link in response header for server push
|
||||
func (c Context) Push(link string) string {
|
||||
if c.responseHeader == nil {
|
||||
return ""
|
||||
}
|
||||
c.responseHeader.Add("Link", "<"+link+">; rel=preload")
|
||||
return ""
|
||||
}
|
||||
|
||||
// buffer pool for .Include context actions
|
||||
var includeBufs = sync.Pool{
|
||||
New: func() interface{} {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -731,8 +732,9 @@ func initTestContext() (Context, error) {
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
res := httptest.NewRecorder()
|
||||
|
||||
return Context{Root: http.Dir(os.TempDir()), Req: request}, nil
|
||||
return Context{Root: http.Dir(os.TempDir()), responseHeader: res.Header(), Req: request}, nil
|
||||
}
|
||||
|
||||
func getContextOrFail(t *testing.T) Context {
|
||||
@@ -874,3 +876,35 @@ func TestFiles(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
for name, c := range map[string]struct {
|
||||
input string
|
||||
expectLinks []string
|
||||
}{
|
||||
"oneLink": {
|
||||
input: `{{.Push "/test.css"}}`,
|
||||
expectLinks: []string{"</test.css>; rel=preload"},
|
||||
},
|
||||
"multipleLinks": {
|
||||
input: `{{.Push "/test1.css"}} {{.Push "/test2.css"}}`,
|
||||
expectLinks: []string{"</test1.css>; rel=preload", "</test2.css>; rel=preload"},
|
||||
},
|
||||
} {
|
||||
c := c
|
||||
t.Run(name, func(t *testing.T) {
|
||||
ctx := getContextOrFail(t)
|
||||
tmpl, err := template.New("").Parse(c.input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = tmpl.Execute(ioutil.Discard, ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := ctx.responseHeader["Link"]; !reflect.DeepEqual(got, c.expectLinks) {
|
||||
t.Errorf("Result not match: expect %v, but got %v", c.expectLinks, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user