63 lines
1.9 KiB
Go
63 lines
1.9 KiB
Go
package web
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// assetHandler mirrors how the router mounts the embedded assets: the request
|
|
// path has "/static/" stripped, and the file system is expected to be rooted at
|
|
// the assets themselves.
|
|
func assetHandler() http.Handler {
|
|
return http.StripPrefix("/static/", http.FileServerFS(StaticFS()))
|
|
}
|
|
|
|
// Static assets must actually be served. A 404 here does not look like a
|
|
// missing file in the browser: the 404 body arrives as text/plain under
|
|
// X-Content-Type-Options: nosniff, so the browser refuses it and reports
|
|
// corrupted content, which sends you looking for an encoding bug instead.
|
|
func TestStaticAssetsAreServed(t *testing.T) {
|
|
h := assetHandler()
|
|
|
|
for _, asset := range []struct{ path, wantType string }{
|
|
{"/static/app.css", "text/css"},
|
|
{"/static/public.css", "text/css"},
|
|
{"/static/app.js", "javascript"},
|
|
{"/static/favicon.svg", "image/svg+xml"},
|
|
} {
|
|
t.Run(asset.path, func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, asset.path, nil))
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200 — the asset is not reachable at the path "+
|
|
"the templates reference", w.Code)
|
|
}
|
|
if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, asset.wantType) {
|
|
t.Fatalf("Content-Type = %q, want something containing %q", ct, asset.wantType)
|
|
}
|
|
if w.Body.Len() == 0 {
|
|
t.Fatal("the asset is empty")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Path traversal must not escape the asset root.
|
|
func TestStaticAssetsRefuseTraversal(t *testing.T) {
|
|
h := assetHandler()
|
|
for _, p := range []string{
|
|
"/static/../render.go",
|
|
"/static/../../go.mod",
|
|
"/static/..%2f..%2fgo.mod",
|
|
} {
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, p, nil))
|
|
if w.Code == http.StatusOK {
|
|
t.Errorf("%s was served with 200; it must not escape the asset root", p)
|
|
}
|
|
}
|
|
}
|