Push resources for indexFiles when surfing to directories

Use httpserver.IndexFile() to determine index files

Test if middleware pushes indexfile when requesting directory

Fix codereview issues

Serve original request first, push later

Revert "Serve original request first, push later"

This reverts commit 2c66f01115747e5665ba7f2d33e2fd551dc31877.
This commit is contained in:
Thomas De Keulenaer 2017-07-06 09:24:01 +02:00
parent 40b52fb02e
commit 20f76a256e
4 changed files with 72 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import (
"strings" "strings"
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
"github.com/mholt/caddy/caddyhttp/staticfiles"
) )
func (h Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (h Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
@ -25,7 +26,13 @@ func (h Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, erro
// push first // push first
outer: outer:
for _, rule := range h.Rules { for _, rule := range h.Rules {
if httpserver.Path(r.URL.Path).Matches(rule.Path) { urlPath := r.URL.Path
matches := httpserver.Path(urlPath).Matches(rule.Path)
// Also check IndexPages when requesting a directory
if !matches {
_, matches = httpserver.IndexFile(h.Root, urlPath, staticfiles.IndexPages)
}
if matches {
for _, resource := range rule.Resources { for _, resource := range rule.Resources {
pushErr := pusher.Push(resource.Path, &http.PushOptions{ pushErr := pusher.Push(resource.Path, &http.PushOptions{
Method: resource.Method, Method: resource.Method,

View File

@ -2,8 +2,11 @@ package push
import ( import (
"errors" "errors"
"io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"path/filepath"
"reflect" "reflect"
"testing" "testing"
@ -307,6 +310,63 @@ func TestMiddlewareShouldInterceptLinkHeaderPusherError(t *testing.T) {
comparePushedResources(t, expectedPushedResources, pushingWriter.pushed) comparePushedResources(t, expectedPushedResources, pushingWriter.pushed)
} }
func TestMiddlewareShouldPushIndexFile(t *testing.T) {
// given
indexFile := "/index.html"
request, err := http.NewRequest(http.MethodGet, "/", nil) // Request root directory, not indexfile itself
if err != nil {
t.Fatalf("Could not create HTTP request: %v", err)
}
root, err := ioutil.TempDir("", "caddy")
if err != nil {
t.Fatalf("Could not create temporary directory: %v", err)
}
defer os.Remove(root)
middleware := Middleware{
Next: httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
return 0, nil
}),
Rules: []Rule{
{Path: indexFile, Resources: []Resource{
{Path: "/index.css", Method: http.MethodGet},
}},
},
Root: http.Dir(root),
}
indexFilePath := filepath.Join(root, indexFile)
_, err = os.Create(indexFilePath)
if err != nil {
t.Fatalf("Could not create index file: %s: %v", indexFile, err)
}
defer os.Remove(indexFilePath)
pushingWriter := &MockedPusher{
ResponseWriter: httptest.NewRecorder(),
returnedError: errors.New("Cannot push right now"),
}
// when
_, err2 := middleware.ServeHTTP(pushingWriter, request)
// then
if err2 != nil {
t.Error("Should not return error")
}
expectedPushedResources := map[string]*http.PushOptions{
"/index.css": {
Method: http.MethodGet,
Header: http.Header{},
},
}
comparePushedResources(t, expectedPushedResources, pushingWriter.pushed)
}
func comparePushedResources(t *testing.T, expected, actual map[string]*http.PushOptions) { func comparePushedResources(t *testing.T, expected, actual map[string]*http.PushOptions) {
if len(expected) != len(actual) { if len(expected) != len(actual) {
t.Errorf("Expected %d pushed resources, actual: %d", len(expected), len(actual)) t.Errorf("Expected %d pushed resources, actual: %d", len(expected), len(actual))

View File

@ -24,6 +24,7 @@ type (
Middleware struct { Middleware struct {
Next httpserver.Handler Next httpserver.Handler
Rules []Rule Rules []Rule
Root http.FileSystem
} }
ruleOp func([]Resource) ruleOp func([]Resource)

View File

@ -34,8 +34,9 @@ func setup(c *caddy.Controller) error {
return err return err
} }
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { cfg := httpserver.GetConfig(c)
return Middleware{Next: next, Rules: rules} cfg.AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
return Middleware{Next: next, Rules: rules, Root: http.Dir(cfg.Root)}
}) })
return nil return nil