Skip to content

Support redirects from frame reloads - #11667

Open
brophdawg11 wants to merge 1 commit into
mainfrom
brophdawg11/frame-reload-redirects
Open

Support redirects from frame reloads#11667
brophdawg11 wants to merge 1 commit into
mainfrom
brophdawg11/frame-reload-redirects

Conversation

@brophdawg11

@brophdawg11 brophdawg11 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Frame resolvers currently have to unwrap fetched responses into content, which hides whether fetch() followed a redirect. This allows the resolver to return the Response so 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.

  • Adds FrameResolution as frame content or a Response.
  • Streams response bodies and uses the final response URL as the frame source when Response.redirected is true.
  • Replaces the navigation URL for redirected frame reloads initiated by frame navigation.
  • Demonstrates the behavior with a 303 redirect from /settings to /settings/overview in the frame-navigation demo.
  • Supersedes the redirect portion of Support form-driven frame navigation #11632; form submissions are split into stacked follow-up Support form-driven frame navigation #11668.
run({
  async resolveFrame(src, signal, target) {
    let headers = new Headers({ Accept: 'text/html' })
    if (target) headers.set('X-Remix-Target', target)
    return fetch(src, { headers, signal })
  },
})

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Preview Build Available

A 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +102 to +112
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,
})
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a navigational frame reload followed a redirect, replace the current history entry with the redirected location.

@brophdawg11 brophdawg11 self-assigned this Aug 5, 2026
@brophdawg11
brophdawg11 force-pushed the brophdawg11/frame-reload-redirects branch from 9489085 to fd9bf3f Compare August 7, 2026 19:04
@brophdawg11
brophdawg11 marked this pull request as ready for review August 7, 2026 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant