mirror of
https://github.com/hanzoai/ingress.git
synced 2026-10-20 15:07:40 +00:00
Name the types the runtime image cannot look up
The static plane sets nosniff, which turns an unknown Content-Type from a guess into a refusal. Go's built-in table stops at the web's first dozen extensions and takes the rest from the system mime.types, which the distroless runtime does not ship — so .md and .woff2 resolve on a developer's box and answer empty in production. hanzoskills.com publishes a markdown twin of every document, and a browser opening one was offered a download instead of a page. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -22,6 +22,26 @@ import (
|
||||
|
||||
const typeName = "StaticFiles"
|
||||
|
||||
// Extensions Go's built-in table does not carry. It falls back to the system
|
||||
// mime.types, which a distroless image does not ship, so on a developer's box
|
||||
// these resolve and in production they come back empty — and this plane sets
|
||||
// `nosniff`, so an empty answer means the browser is told the type is unknown
|
||||
// and forbidden to guess. Markdown served that way is offered as a download
|
||||
// instead of a page; hanzoskills.com publishes a .md twin of every document.
|
||||
func init() {
|
||||
for ext, typ := range map[string]string{
|
||||
".md": "text/markdown; charset=utf-8",
|
||||
".markdown": "text/markdown; charset=utf-8",
|
||||
".woff": "font/woff",
|
||||
".woff2": "font/woff2",
|
||||
".ttf": "font/ttf",
|
||||
".otf": "font/otf",
|
||||
} {
|
||||
// AddExtensionType only returns an error on a malformed extension.
|
||||
_ = mime.AddExtensionType(ext, typ)
|
||||
}
|
||||
}
|
||||
|
||||
type dirEntry struct {
|
||||
Name string
|
||||
Size int64
|
||||
|
||||
@@ -107,3 +107,42 @@ func TestLocalErrorPage(t *testing.T) {
|
||||
t.Fatalf("local error page: status=%d body=%q", resp.StatusCode, body)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNosniffTypesAreRegistered proves every extension this plane serves gets a
|
||||
// Content-Type. The pairing is what makes it matter: the handler sets
|
||||
// `X-Content-Type-Options: nosniff`, so a missing type is not a browser falling
|
||||
// back to a guess, it is a browser refusing to render. Go's built-in table stops
|
||||
// at the web's first dozen extensions and the rest come from the system
|
||||
// mime.types, which the runtime image does not ship — so this passed on a
|
||||
// developer's box and failed in production until the types were registered here.
|
||||
func TestNosniffTypesAreRegistered(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
for name, body := range map[string]string{
|
||||
"readme.md": "# hello\n",
|
||||
"font.woff2": "\x77OF2",
|
||||
} {
|
||||
if err := os.WriteFile(filepath.Join(dir, name), []byte(body), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
srv := httptest.NewServer(newLocal(t, dynamic.StaticFiles{Root: dir}))
|
||||
defer srv.Close()
|
||||
|
||||
for path, want := range map[string]string{
|
||||
"/readme.md": "text/markdown",
|
||||
"/font.woff2": "font/woff2",
|
||||
} {
|
||||
resp, err := srv.Client().Get(srv.URL + path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
if got := resp.Header.Get("Content-Type"); !strings.HasPrefix(got, want) {
|
||||
t.Errorf("%s: Content-Type %q, want %s — with nosniff the browser will not render this", path, got, want)
|
||||
}
|
||||
if resp.Header.Get("X-Content-Type-Options") != "nosniff" {
|
||||
t.Errorf("%s: nosniff missing; this test is only meaningful beside it", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user