fully-react
Version:
React Server for Vite
190 lines (187 loc) • 5.65 kB
JavaScript
import {
getURLFromRedirectError,
isRedirectError
} from "./chunk-EHJL7JPJ.js";
import {
requestAsyncContext
} from "./chunk-UXXZ4F7M.js";
import {
createHTMLResponse
} from "./chunk-K4W7QR7B.js";
import {
createActionResponse,
createServerComponentResponse
} from "./chunk-U26WWCBL.js";
import {
decodeReply
} from "./chunk-2LNACUKM.js";
// src/server/handler.tsx
import { createRouter } from "@hattip/router";
async function handleActionRequest(request, env) {
let actionId = request.headers.get("x-action");
const isAction = !!actionId;
const isForm = request.headers.get("content-type") === "application/x-www-form-urlencoded";
const isMultiPartForm = request.headers.get("content-type")?.startsWith("multipart/form-data");
if (!isAction && !isForm && !isMultiPartForm) {
return new Response("Not Found", { status: 404 });
}
let data;
if (isForm || isMultiPartForm) {
const formData = await request.formData();
data = [formData];
actionId = formData.get("$$id");
} else {
const encodedArgs = await request.text();
data = await decodeReply(encodedArgs);
}
const [filePath, name] = actionId.split("#");
const action = (await env.loadModule(filePath))[name];
const isMutating = request.headers.get("x-mutation") === "1";
if (isMutating) {
const responseInit = {};
return requestAsyncContext.run(
{ request, response: responseInit },
async () => {
try {
await action(...data);
const url = new URL(request.url);
return createServerComponentResponse(
"root",
{
url: url.href,
searchParams: Object.fromEntries(url.searchParams.entries()),
headers: Object.fromEntries(request.headers.entries()),
params: {}
},
env
);
} catch (e) {
console.error(e);
if (isRedirectError(e)) {
const redirectPath = getURLFromRedirectError(e);
const url = new URL(redirectPath, request.url);
return createServerComponentResponse(
"root",
{
url: url.href,
searchParams: Object.fromEntries(url.searchParams.entries()),
headers: Object.fromEntries(request.headers.entries()),
params: {}
},
env,
{
status: 200,
headers: {
"x-redirect": redirectPath
}
}
);
}
}
}
);
} else if (isForm || isMultiPartForm) {
try {
await action(...data);
const url = new URL(request.url);
const responseInit = {};
return requestAsyncContext.run(
{ request, response: responseInit },
async () => {
return createHTMLResponse(
"root",
{
url: url.href,
searchParams: Object.fromEntries(url.searchParams.entries()),
headers: Object.fromEntries(request.headers.entries()),
params: {}
},
env,
responseInit
);
}
);
} catch (e) {
if (isRedirectError(e)) {
return new Response("", {
status: 302,
headers: {
Location: getURLFromRedirectError(e)
}
});
}
}
}
return createActionResponse(action, data, env);
}
async function handlePageRequest(request, env) {
const url = new URL(request.url);
const responseInit = {};
const response = await requestAsyncContext.run(
{ request, response: responseInit },
async () => await createHTMLResponse(
"root",
{
url: request.url,
searchParams: Object.fromEntries(url.searchParams.entries()),
headers: Object.fromEntries(request.headers.entries()),
params: {}
},
env,
responseInit
)
);
console.log("response", response.status, response.url);
return response;
}
async function handleServerComponentRequest(request, env) {
const url = new URL(request.headers.get("x-navigate") ?? "/", request.url);
const response = {};
return requestAsyncContext.run(
{ request, response },
() => createServerComponentResponse(
"root",
{
url: request.url,
searchParams: Object.fromEntries(url.searchParams.entries()),
headers: Object.fromEntries(request.headers.entries()),
params: {}
},
env,
response
)
);
}
function createServerRouter(env) {
const router = createRouter();
Object.entries(env.routesConfig).forEach(([entry, route]) => {
if (route.routeHandler) {
router.get(route.path, async (context) => {
const mod = await env.loadModule(route.file);
const handler = mod[context.request.method];
return await handler(context.request);
});
router.post(route.path, async (context) => {
const mod = await env.loadModule(route.file);
const handler = mod[context.request.method];
return await handler(context.request);
});
}
});
router.post("/*", async (context) => {
return handleActionRequest(context.request, env);
});
router.get("/*", async (context) => {
if (context.request.headers.get("accept") === "text/x-component") {
return handleServerComponentRequest(context.request, env);
}
return await handlePageRequest(context.request, env);
});
return router;
}
export {
handleActionRequest,
handlePageRequest,
handleServerComponentRequest,
createServerRouter
};