-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for incorrect Content-Type headers returned for Admin UI bundles #2864
Conversation
🦋 Changeset is good to goLatest commit: 2e56648 We got this. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
packages/app-admin-ui/index.js
Outdated
// We need to reset the res 'Content-Type' otherwise it gets replaced by the format we've matched on: '*/*'. | ||
// Returning a wildcard mimetype causes problems if a 'X-Content-Type-Options: nosniff' header is also set. | ||
// See.. https://github.com/keystonejs/keystone/issues/2741 | ||
res.type(path.extname(req.url)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when req.url
= /foo/bar
?
Wouldn't we want the content type to be text/html
then? Or maybe */*
to let the client decide?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we control 100% of the requests? In the adminUI... which so far I can only see /admin/js/*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like this?
res.type(path.extname(req.url)); | |
const extension = path.extname(req.url); | |
res.type(extension ? extension : '*/*'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dominikwilkowski This express app handles everything under /admin
, which could include custom pages. Not to mention the pages such as /admin/todos
which doesn't have an extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point. So...
-
If I request
/admin/blerg
from the browser (address bar), the browser (Chrome in this case) adds a sensibleAccept
header of..Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Which works fine as it matches the
text/html
resolver (returns withContent-Type: text/html; charset=utf-8
). -
If I request
/admin/blerg
without anAccept
header, it hits the*/*
format resolver and theContent-Type
is returned asapplication/octet-stream
. Presumably this is some kind of default that's applied since we're passingres.type()
and empty string. -
If I request with an unrecognised
Accept
header (food/pasta
) it hits thedefault
format resolver, returning withContent-Type: text/html; charset=UTF-8
which is correct for the content -- the main html page for the admin UI.
This all seems to be true regardless of the depth of the path, trailing slashes, etc.
Point 2 is probably wrong. The content being returned is actual html; the incorrect mime type here is our fault -- I've patched to only override if a file extension is present, meaning it will return */*
as before.
Note this still isn't totally correct. If we removed the res.format()
block entirely, these requests would return text/html
. But as you say, at least the browser can decide (and it's still correct more often than what we have now).
… (eg. bundles) (keystonejs#2864) * Fix for incorrect Content-Type headers returned for Admin UI bundles * Changeset 🦋✨ * Being more sensible about paths without a file extension
Fixes #2741.
When the Express
res.format()
function matches a request (to a non-default function) it replaces the responsesContent-Type
header with the key it matched on. This causes our*/*
format handler (which is basically a noop) to return requests with header ofContent-Type: */*
. This in turn causes problems if aX-Content-Type-Options: nosniff
header is also set on the request (ie. somewhere else in the Express middleware, by a reverse proxy, etc.).We can fix this by resetting the
Content-Type
header with a mime-type derived from the requested files extension.Unfortunately, despite being quite redundant, we can't just remove the
*/*
handler. Doing so causes requests with anAccept: */*
header or noAccept
at all to fall though to thetext/html
handler, rather than the default.The
default
handler itself doesn't require this additional logic as Express has already given the response a correctContent-Type
header and doesn't override it when thedefault
format handler is used. If thetext/html
handler is hit, the overriddenContent-Type
is correctly set totext/html
.