mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-25 17:56:34 +08:00
Added the Context to the browse directive
Moved the Context type to middleware and exported it. Users can use .Include and others in browse directive templating Created test for the templates directive.
This commit is contained in:
parent
fcf2622c26
commit
f536bc94b2
|
@ -2,8 +2,8 @@ package setup
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"text/template"
|
||||
|
||||
"github.com/mholt/caddy/middleware"
|
||||
"github.com/mholt/caddy/middleware/browse"
|
||||
|
|
|
@ -5,13 +5,13 @@ package browse
|
|||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
|
@ -51,6 +51,8 @@ type Listing struct {
|
|||
|
||||
// And which order
|
||||
Order string
|
||||
|
||||
middleware.Context
|
||||
}
|
||||
|
||||
// FileInfo is the info about a particular file or directory
|
||||
|
@ -135,8 +137,9 @@ var IndexPages = []string{
|
|||
"default.htm",
|
||||
}
|
||||
|
||||
func directoryListing(files []os.FileInfo, urlPath string, canGoUp bool) (Listing, error) {
|
||||
func directoryListing(files []os.FileInfo, r *http.Request, canGoUp bool, root string) (Listing, error) {
|
||||
var fileinfos []FileInfo
|
||||
var urlPath = r.URL.Path
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
|
||||
|
@ -168,6 +171,11 @@ func directoryListing(files []os.FileInfo, urlPath string, canGoUp bool) (Listin
|
|||
Path: urlPath,
|
||||
CanGoUp: canGoUp,
|
||||
Items: fileinfos,
|
||||
Context: middleware.Context{
|
||||
Root: http.Dir(root),
|
||||
Req: r,
|
||||
URL: r.URL,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -222,7 +230,7 @@ func (b Browse) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
|||
}
|
||||
}
|
||||
// Assemble listing of directory contents
|
||||
listing, err := directoryListing(files, r.URL.Path, canGoUp)
|
||||
listing, err := directoryListing(files, r, canGoUp, b.Root)
|
||||
if err != nil { // directory isn't browsable
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package templates
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -8,23 +8,22 @@ import (
|
|||
"net/url"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/mholt/caddy/middleware"
|
||||
)
|
||||
|
||||
// This file contains the context and functions available for
|
||||
// use in the templates.
|
||||
|
||||
// context is the context with which templates are executed.
|
||||
type context struct {
|
||||
root http.FileSystem
|
||||
req *http.Request
|
||||
URL *url.URL
|
||||
type Context struct {
|
||||
Root http.FileSystem
|
||||
Req *http.Request
|
||||
// This is used to access information about the URL.
|
||||
URL *url.URL
|
||||
}
|
||||
|
||||
// Include returns the contents of filename relative to the site root
|
||||
func (c context) Include(filename string) (string, error) {
|
||||
file, err := c.root.Open(filename)
|
||||
func (c Context) Include(filename string) (string, error) {
|
||||
file, err := c.Root.Open(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -50,13 +49,13 @@ func (c context) Include(filename string) (string, error) {
|
|||
}
|
||||
|
||||
// Date returns the current timestamp in the specified format
|
||||
func (c context) Date(format string) string {
|
||||
func (c Context) Date(format string) string {
|
||||
return time.Now().Format(format)
|
||||
}
|
||||
|
||||
// Cookie gets the value of a cookie with name name.
|
||||
func (c context) Cookie(name string) string {
|
||||
cookies := c.req.Cookies()
|
||||
func (c Context) Cookie(name string) string {
|
||||
cookies := c.Req.Cookies()
|
||||
for _, cookie := range cookies {
|
||||
if cookie.Name == name {
|
||||
return cookie.Value
|
||||
|
@ -66,15 +65,15 @@ func (c context) Cookie(name string) string {
|
|||
}
|
||||
|
||||
// Header gets the value of a request header with field name.
|
||||
func (c context) Header(name string) string {
|
||||
return c.req.Header.Get(name)
|
||||
func (c Context) Header(name string) string {
|
||||
return c.Req.Header.Get(name)
|
||||
}
|
||||
|
||||
// IP gets the (remote) IP address of the client making the request.
|
||||
func (c context) IP() string {
|
||||
ip, _, err := net.SplitHostPort(c.req.RemoteAddr)
|
||||
func (c Context) IP() string {
|
||||
ip, _, err := net.SplitHostPort(c.Req.RemoteAddr)
|
||||
if err != nil {
|
||||
return c.req.RemoteAddr
|
||||
return c.Req.RemoteAddr
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
@ -82,14 +81,14 @@ func (c context) IP() string {
|
|||
// URI returns the raw, unprocessed request URI (including query
|
||||
// string and hash) obtained directly from the Request-Line of
|
||||
// the HTTP request.
|
||||
func (c context) URI() string {
|
||||
return c.req.RequestURI
|
||||
func (c Context) URI() string {
|
||||
return c.Req.RequestURI
|
||||
}
|
||||
|
||||
// Host returns the hostname portion of the Host header
|
||||
// from the HTTP request.
|
||||
func (c context) Host() (string, error) {
|
||||
host, _, err := net.SplitHostPort(c.req.Host)
|
||||
func (c Context) Host() (string, error) {
|
||||
host, _, err := net.SplitHostPort(c.Req.Host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -97,8 +96,8 @@ func (c context) Host() (string, error) {
|
|||
}
|
||||
|
||||
// Port returns the port portion of the Host header if specified.
|
||||
func (c context) Port() (string, error) {
|
||||
_, port, err := net.SplitHostPort(c.req.Host)
|
||||
func (c Context) Port() (string, error) {
|
||||
_, port, err := net.SplitHostPort(c.Req.Host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -106,12 +105,12 @@ func (c context) Port() (string, error) {
|
|||
}
|
||||
|
||||
// Method returns the method (GET, POST, etc.) of the request.
|
||||
func (c context) Method() string {
|
||||
return c.req.Method
|
||||
func (c Context) Method() string {
|
||||
return c.Req.Method
|
||||
}
|
||||
|
||||
// PathMatches returns true if the path portion of the request
|
||||
// URL matches pattern.
|
||||
func (c context) PathMatches(pattern string) bool {
|
||||
return middleware.Path(c.req.URL.Path).Matches(pattern)
|
||||
func (c Context) PathMatches(pattern string) bool {
|
||||
return Path(c.Req.URL.Path).Matches(pattern)
|
||||
}
|
1
middleware/templates/header.html
Normal file
1
middleware/templates/header.html
Normal file
|
@ -0,0 +1 @@
|
|||
<h1>Header title</h1>
|
1
middleware/templates/images/header.html
Normal file
1
middleware/templates/images/header.html
Normal file
|
@ -0,0 +1 @@
|
|||
<h1>Header title</h1>
|
1
middleware/templates/images/img.htm
Normal file
1
middleware/templates/images/img.htm
Normal file
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><title>img</title></head><body>{{.Include "header.html"}}</body></html>
|
1
middleware/templates/photos/test.html
Normal file
1
middleware/templates/photos/test.html
Normal file
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><title>test page</title></head><body>{{.Include "../header.html"}}</body></html>
|
1
middleware/templates/root.html
Normal file
1
middleware/templates/root.html
Normal file
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><title>root</title></head><body>{{.Include "header.html"}}</body></html>
|
|
@ -31,7 +31,7 @@ func (t Templates) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
|||
for _, ext := range rule.Extensions {
|
||||
if reqExt == ext {
|
||||
// Create execution context
|
||||
ctx := context{root: t.FileSys, req: r, URL: r.URL}
|
||||
ctx := middleware.Context{Root: t.FileSys, Req: r, URL: r.URL}
|
||||
|
||||
// Build the template
|
||||
tpl, err := template.ParseFiles(filepath.Join(t.Root, fpath))
|
||||
|
|
121
middleware/templates/templates_test.go
Normal file
121
middleware/templates/templates_test.go
Normal file
|
@ -0,0 +1,121 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/mholt/caddy/middleware"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
tmpl := Templates{
|
||||
Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
return 0, nil
|
||||
}),
|
||||
Rules: []Rule{
|
||||
Rule{
|
||||
Extensions: []string{".html"},
|
||||
IndexFiles: []string{"index.html"},
|
||||
Path: "/photos",
|
||||
},
|
||||
Rule{
|
||||
Extensions: []string{".html", ".htm"},
|
||||
IndexFiles: []string{"index.html", "index.htm"},
|
||||
Path: "/images",
|
||||
},
|
||||
},
|
||||
Root: ".",
|
||||
FileSys: http.Dir("."),
|
||||
}
|
||||
|
||||
tmplroot := Templates{
|
||||
Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
return 0, nil
|
||||
}),
|
||||
Rules: []Rule{
|
||||
Rule{
|
||||
Extensions: []string{".html"},
|
||||
IndexFiles: []string{"index.html"},
|
||||
Path: "/",
|
||||
},
|
||||
},
|
||||
Root: ".",
|
||||
FileSys: http.Dir("."),
|
||||
}
|
||||
|
||||
/*
|
||||
* Test tmpl on /photos/test.html
|
||||
*/
|
||||
req, err := http.NewRequest("GET", "/photos/test.html", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Test: Could not create HTTP request: %v", err)
|
||||
}
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
tmpl.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
respBody := rec.Body.String()
|
||||
expectedBody := `<!DOCTYPE html><html><head><title>test page</title></head><body><h1>Header title</h1>
|
||||
</body></html>
|
||||
`
|
||||
|
||||
if respBody != expectedBody {
|
||||
t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
|
||||
}
|
||||
|
||||
/*
|
||||
* Test tmpl on /images/img.htm
|
||||
*/
|
||||
req, err = http.NewRequest("GET", "/images/img.htm", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create HTTP request: %v", err)
|
||||
}
|
||||
|
||||
rec = httptest.NewRecorder()
|
||||
|
||||
tmpl.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
respBody = rec.Body.String()
|
||||
expectedBody = `<!DOCTYPE html><html><head><title>img</title></head><body><h1>Header title</h1>
|
||||
</body></html>
|
||||
`
|
||||
|
||||
if respBody != expectedBody {
|
||||
t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
|
||||
}
|
||||
|
||||
/*
|
||||
* Test tmplroot on /root.html
|
||||
*/
|
||||
req, err = http.NewRequest("GET", "/root.html", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create HTTP request: %v", err)
|
||||
}
|
||||
|
||||
rec = httptest.NewRecorder()
|
||||
|
||||
tmplroot.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Test: Wrong response code: %d, should be %d", rec.Code, http.StatusOK)
|
||||
}
|
||||
|
||||
respBody = rec.Body.String()
|
||||
expectedBody = `<!DOCTYPE html><html><head><title>root</title></head><body><h1>Header title</h1>
|
||||
</body></html>
|
||||
`
|
||||
|
||||
if respBody != expectedBody {
|
||||
t.Fatalf("Test: the expected body %v is different from the response one: %v", expectedBody, respBody)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user