Support redirects from frame reloads - #11667
Conversation
Preview Build AvailableA preview build has been created for this PR. You can install it using: pnpm install "remix-run/remix#preview/pr-11667&path:packages/remix"This preview build will be updated automatically as you push new commits. |
|
|
||
| if (res.body) return res.body | ||
| return await res.text() | ||
| return res |
There was a problem hiding this comment.
I'm on the fence about whether we want to own the response unwrapping. It may make more sense to leave this all in userland resolveFrame code and let them return something akin to our internal unwrapFrameResolution utility - and then we would only own the navigation API touchpoints.
function resolveFrame(src, signal, target) {
let url = new URL(src, window.location.href)
let res = await fetch(url, ...);
let content = res.body ? res.body : await res.text();
if (res.redirected && res.url) {
return { content, redirectTo: res.url };
}
return content;
}| let isSubFrameRequest = | ||
| context.request.headers.get('X-Remix-Frame') === 'true' && | ||
| context.request.headers.get('X-Remix-Target') != null | ||
| if (isSubFrameRequest) { |
There was a problem hiding this comment.
Sub-frames are trickier so we keep them on the old paradigm. We can't return full top frame content from the auth page and insert it into the settings frame. I'm sure this is somewhat solvable by returning metadata that tells the browser to instead replace the top level frame content, but might not be worth the complexity. Happy to give it a go if we want.
| if (frame.src !== requestedFrameSrc) { | ||
| let redirectedSrc = frame.src | ||
| let redirectedState = { ...state, src: redirectedSrc } | ||
| // Start the successor navigation without awaiting it: this handler must settle before | ||
| // the replacement navigation can finish. | ||
| navigation.navigate(redirectedSrc, { | ||
| history: 'replace', | ||
| state: redirectedState, | ||
| info: { type: frameRedirectNavigationInfoType } satisfies FrameRedirectNavigationInfo, | ||
| }) | ||
| } |
There was a problem hiding this comment.
If a navigational frame reload followed a redirect, replace the current history entry with the redirected location.
9489085 to
fd9bf3f
Compare
Frame resolvers currently have to unwrap fetched responses into content, which hides whether
fetch()followed a redirect. This allows the resolver to return theResponseso the frame runtime can preserve streaming and retain the final response URL. A redirected response updates the frame source; when the reload is servicing an intercepted navigation, the runtime also replaces the navigation URL with the final destination.FrameResolutionas frame content or aResponse.Response.redirectedis true.303redirect from/settingsto/settings/overviewin the frame-navigation demo.