Fix Edit in Planner: create session via API, avoid URL size limit
GPX data was being encoded in URL params, causing HTTP 431 (Request Header Fields Too Large). Now the Journal creates a Planner session via POST to /api/sessions with GPX in the request body, then redirects to the session URL (154 chars vs 100KB+). Also moved edit-in-planner logic to dedicated API route for proper JSON response handling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8559b89be6
commit
155d36e94c
3 changed files with 45 additions and 29 deletions
|
|
@ -13,5 +13,6 @@ export default [
|
|||
route("routes/:id", "routes/routes.$id.tsx"),
|
||||
route("routes/:id/edit", "routes/routes.$id.edit.tsx"),
|
||||
route("api/routes/:id/callback", "routes/api.routes.$id.callback.ts"),
|
||||
route("api/routes/:id/edit-in-planner", "routes/api.routes.$id.edit-in-planner.ts"),
|
||||
route("users/:username", "routes/users.$username.tsx"),
|
||||
] satisfies RouteConfig;
|
||||
|
|
|
|||
41
apps/journal/app/routes/api.routes.$id.edit-in-planner.ts
Normal file
41
apps/journal/app/routes/api.routes.$id.edit-in-planner.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { data } from "react-router";
|
||||
import type { Route } from "./+types/api.routes.$id.edit-in-planner";
|
||||
import { getSessionUser } from "~/lib/auth.server";
|
||||
import { getRouteWithVersions } from "~/lib/routes.server";
|
||||
import { createRouteToken } from "~/lib/jwt.server";
|
||||
|
||||
export async function action({ params, request }: Route.ActionArgs) {
|
||||
const user = await getSessionUser(request);
|
||||
if (!user) return data({ error: "Not authenticated" }, { status: 401 });
|
||||
|
||||
const route = await getRouteWithVersions(params.id);
|
||||
if (!route) return data({ error: "Route not found" }, { status: 404 });
|
||||
if (route.ownerId !== user.id) return data({ error: "Not authorized" }, { status: 403 });
|
||||
|
||||
const token = await createRouteToken(params.id);
|
||||
const origin = process.env.ORIGIN ?? "http://localhost:3000";
|
||||
const callbackUrl = `${origin}/api/routes/${params.id}/callback`;
|
||||
const plannerUrl = process.env.PLANNER_URL ?? "http://localhost:3001";
|
||||
const returnUrl = `${origin}/routes/${params.id}`;
|
||||
|
||||
// Create Planner session via API (POST body, not URL params)
|
||||
const sessionResp = await fetch(`${plannerUrl}/api/sessions`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
callbackUrl,
|
||||
callbackToken: token,
|
||||
gpx: route.gpx ?? undefined,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!sessionResp.ok) {
|
||||
return data({ error: "Failed to create Planner session" }, { status: 502 });
|
||||
}
|
||||
|
||||
const session = (await sessionResp.json()) as { url: string };
|
||||
|
||||
return data({
|
||||
url: `${plannerUrl}${session.url}?returnUrl=${encodeURIComponent(returnUrl)}`,
|
||||
});
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ import { data, redirect } from "react-router";
|
|||
import type { Route } from "./+types/routes.$id";
|
||||
import { getSessionUser } from "~/lib/auth.server";
|
||||
import { getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/routes.server";
|
||||
import { createRouteToken } from "~/lib/jwt.server";
|
||||
|
||||
|
||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
||||
|
|
@ -75,29 +74,6 @@ export async function action({ params, request }: Route.ActionArgs) {
|
|||
});
|
||||
}
|
||||
|
||||
if (intent === "edit-in-planner") {
|
||||
const route = await getRouteWithVersions(params.id);
|
||||
if (!route) return data({ error: "Route not found" }, { status: 404 });
|
||||
|
||||
const token = await createRouteToken(params.id);
|
||||
const origin = process.env.ORIGIN ?? "http://localhost:3000";
|
||||
const callbackUrl = `${origin}/api/routes/${params.id}/callback`;
|
||||
const plannerUrl = process.env.PLANNER_URL ?? "http://localhost:3001";
|
||||
|
||||
const plannerParams = new URLSearchParams({
|
||||
callback: callbackUrl,
|
||||
token,
|
||||
returnUrl: `${origin}/routes/${params.id}`,
|
||||
});
|
||||
|
||||
// If route has GPX, include it
|
||||
if (route.gpx) {
|
||||
plannerParams.set("gpx", encodeURIComponent(route.gpx));
|
||||
}
|
||||
|
||||
return data({ redirect: `${plannerUrl}/new?${plannerParams}` });
|
||||
}
|
||||
|
||||
return data({ error: "Unknown action" }, { status: 400 });
|
||||
}
|
||||
|
||||
|
|
@ -113,12 +89,10 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
|||
const handleEditInPlanner = useCallback(async () => {
|
||||
setEditLoading(true);
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.set("intent", "edit-in-planner");
|
||||
const resp = await fetch(`/routes/${route.id}`, { method: "POST", body: formData });
|
||||
const resp = await fetch(`/api/routes/${route.id}/edit-in-planner`, { method: "POST" });
|
||||
const result = await resp.json();
|
||||
if (result.redirect) {
|
||||
window.location.href = result.redirect;
|
||||
if (result.url) {
|
||||
window.location.href = result.url;
|
||||
}
|
||||
} finally {
|
||||
setEditLoading(false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue