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", "routes/routes.$id.tsx"),
|
||||||
route("routes/:id/edit", "routes/routes.$id.edit.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/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"),
|
route("users/:username", "routes/users.$username.tsx"),
|
||||||
] satisfies RouteConfig;
|
] 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 type { Route } from "./+types/routes.$id";
|
||||||
import { getSessionUser } from "~/lib/auth.server";
|
import { getSessionUser } from "~/lib/auth.server";
|
||||||
import { getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/routes.server";
|
import { getRouteWithVersions, deleteRoute, updateRoute } from "~/lib/routes.server";
|
||||||
import { createRouteToken } from "~/lib/jwt.server";
|
|
||||||
|
|
||||||
|
|
||||||
export async function loader({ params, request }: Route.LoaderArgs) {
|
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 });
|
return data({ error: "Unknown action" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,12 +89,10 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
||||||
const handleEditInPlanner = useCallback(async () => {
|
const handleEditInPlanner = useCallback(async () => {
|
||||||
setEditLoading(true);
|
setEditLoading(true);
|
||||||
try {
|
try {
|
||||||
const formData = new FormData();
|
const resp = await fetch(`/api/routes/${route.id}/edit-in-planner`, { method: "POST" });
|
||||||
formData.set("intent", "edit-in-planner");
|
|
||||||
const resp = await fetch(`/routes/${route.id}`, { method: "POST", body: formData });
|
|
||||||
const result = await resp.json();
|
const result = await resp.json();
|
||||||
if (result.redirect) {
|
if (result.url) {
|
||||||
window.location.href = result.redirect;
|
window.location.href = result.url;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setEditLoading(false);
|
setEditLoading(false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue