use the platform's dev proxy instead of a worse copy of it
The preview went through a proxy written into this plugin. The platform already had one — /api/dev-proxy/:port/* — and it is better in exactly the ways the copy was worst. Authentication. An iframe navigation cannot carry an Authorization header, and the copy answered that by putting a token on the URL and on every asset the page then requested. The platform's answer is a short-lived cookie obtained by an ordinary authenticated request, and its own comments say why: a token on an iframe URL is a guess about which key the browser stored it under. It had been tried there and rejected before this plugin repeated it. Coverage. The copy rewrote URLs with a regex over the markup, which catches only what is written into the document. The platform injects a script that patches fetch, XMLHttpRequest and WebSocket, so URLs the page BUILDS at runtime are moved as well — which is most of them in a modern dev server. It also normalises `..`, forwards HMR, and has nineteen tests behind it. So the plugin's proxy is gone, previewUrl with it, and the panel does what the platform's Preview panel does: ask for the session, then mount the frame at the dev port. No sandbox attribute, for the reason that panel gives. Without allow-same-origin a frame has an opaque origin and no storage; with allow-same-origin and allow-scripts it can reach up and remove its own sandbox attribute. Claiming a protection that does not hold is worse than not claiming it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -48,18 +48,3 @@ export const originalUrl = (path: string, width: number): string => {
|
||||
const encoded = path.split('/').map(encodeURIComponent).join('/');
|
||||
return `/api/fofos-admin/original/${encoded}?width=${Math.round(width)}&token=${encodeURIComponent(token)}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* The site's own page, proxied through Officer, for the layout preview's iframe.
|
||||
*
|
||||
* Here rather than in the panel for the reason this module exists at all: it is a URL shape carrying a
|
||||
* token, and a second copy of one is a second place to be wrong about it.
|
||||
*
|
||||
* `/api/fofos-admin/...` and NOT `/fofos-admin/...`. The second is the single-page app's own route, so
|
||||
* anything under it that no router claims is answered with Officer's index.html — an iframe pointed
|
||||
* there renders Officer inside Officer, which is precisely what it did.
|
||||
*/
|
||||
export const previewUrl = (path: string): string => {
|
||||
const token = getHeaders()['Authorization']?.replace('Bearer ', '') ?? '';
|
||||
return `/api/fofos-admin/preview/${path.replace(/^\/+/, '')}?token=${encodeURIComponent(token)}`;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user