diff --git a/README.md b/README.md index 6b22b52..c0ea028 100644 --- a/README.md +++ b/README.md @@ -508,18 +508,20 @@ export interface HonoServerOptions extends Omit [!IMPORTANT] -> TLDR: If you encounter a `Error: Unable to decode turbo-stream response` after a redirect from your middleware, try to use `reactRouterRedirect` instead of `c.redirect`. +> TLDR: If you encounter a `Error: Unable to decode turbo-stream response` after a redirect from your middleware, try to use `redirect` instead of `c.redirect`. +> +> `redirect` will use `c.redirect` for "normal" requests and a single-fetch-like response for React Router `.data` requests. > > If the next handler is a Hono middleware (ex: https://github.com/rphlmr/react-router-hono-server/discussions/56), you can use `c.redirect` as usual. > -> You **have to** use the `reactRouterRedirect` helper to redirect from a middleware if the next handler that will receive this redirect is a React Router route. +> You **have to** use the `redirect` helper to redirect from a middleware if the next handler that will receive this redirect is a React Router route. > > It returns a single-fetch-like response. > > If you use `c.redirect`, it will not work as expected and you will get a `Unable to decode turbo-stream response` error. > >```ts -> import { reactRouterRedirect } from "react-router-hono-server/http"; +> import { redirect } from "react-router-hono-server/http"; >``` > > I'm sorry for this inconvenience, I hope it can be "fixed" in future React Router versions. diff --git a/examples/node/protected-routes/app/server.ts b/examples/node/protected-routes/app/server.ts index 06b69fc..748554a 100644 --- a/examples/node/protected-routes/app/server.ts +++ b/examples/node/protected-routes/app/server.ts @@ -1,6 +1,6 @@ import { getConnInfo } from "@hono/node-server/conninfo"; import { createMiddleware } from "hono/factory"; -import { reactRouterRedirect } from "react-router-hono-server/http"; +import { redirect } from "react-router-hono-server/http"; import { createHonoServer } from "react-router-hono-server/node"; console.log("loading server"); @@ -17,7 +17,7 @@ const protectRoutes = createMiddleware(async (c, next) => { console.log("Checking path:", c.req.path); if (c.req.path.includes("/protected")) { - return reactRouterRedirect("/"); + return redirect(c, "/"); } return next(); diff --git a/src/http.ts b/src/http.ts index 3f81860..7ca780a 100644 --- a/src/http.ts +++ b/src/http.ts @@ -1,7 +1,11 @@ +import type { Context } from "hono"; + /** * Redirect to a new location in a way that React Router can handle. * * It follows the Single Fetch Redirect protocol. + * + * @deprecated Use `redirect` instead. `import { reactRouterRedirect } from "react-router-hono-server/http"` */ export function reactRouterRedirect(location: string) { return new Response( @@ -42,3 +46,25 @@ export function reactRouterRedirect(location: string) { } ); } + +/** + * Redirect to a new location. + * + * It follows the Single Fetch Redirect protocol, if the request path ends with `.data`. + */ +export function redirect(c: Context, location: string) { + if (c.req.path.includes(".data")) { + return reactRouterRedirect(location); + } + + return c.redirect(location); +} + +/** + * Get the current request path + * + * If the path ends with `.data` (React Router Single Fetch query), it will be removed. + */ +function getPath(c: Context) { + return c.req.path.replace(".data", ""); +}