mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	Merge pull request #1613 from tw4452852/addlink
Context: add Push action
This commit is contained in:
		
						commit
						4c034f6ad1
					
				@ -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)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -133,11 +133,10 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
 | 
			
		||||
	}
 | 
			
		||||
	lastModTime = latest(lastModTime, fs.ModTime())
 | 
			
		||||
 | 
			
		||||
	ctx := httpserver.Context{
 | 
			
		||||
		Root: md.FileSys,
 | 
			
		||||
		Req:  r,
 | 
			
		||||
		URL:  r.URL,
 | 
			
		||||
	}
 | 
			
		||||
	ctx := httpserver.NewContextWithHeader(w.Header())
 | 
			
		||||
	ctx.Root = md.FileSys
 | 
			
		||||
	ctx.Req = r
 | 
			
		||||
	ctx.URL = r.URL
 | 
			
		||||
	html, err := cfg.Markdown(title(fpath), f, dirents, ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return http.StatusInternalServerError, err
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,10 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
 | 
			
		||||
		for _, ext := range rule.Extensions {
 | 
			
		||||
			if reqExt == ext {
 | 
			
		||||
				// Create execution context
 | 
			
		||||
				ctx := httpserver.Context{Root: t.FileSys, Req: r, URL: r.URL}
 | 
			
		||||
				ctx := httpserver.NewContextWithHeader(w.Header())
 | 
			
		||||
				ctx.Root = t.FileSys
 | 
			
		||||
				ctx.Req = r
 | 
			
		||||
				ctx.URL = r.URL
 | 
			
		||||
 | 
			
		||||
				// New template
 | 
			
		||||
				templateName := filepath.Base(fpath)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user