rasengan
Version:
The modern React Framework
126 lines (125 loc) • 5.11 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { createStaticRouter, StaticRouterProvider, } from 'react-router';
import { logRedirection as log } from '../../core/utils/log.js';
import createRasenganRequest, { createRasenganHeaders, sendRasenganResponse, } from '../node/utils.js';
import { join } from 'path';
import { isStaticRedirectFromConfig, isRedirectResponse, extractMetaFromRRContext, extractHeadersFromRRContext, } from './utils.js';
import { renderToString } from '../node/rendering.js';
import { TemplateLayout } from '../../entries/server/index.js';
/**
* Handle redirect request
* @param req
* @param res
* @param options
* @returns
*/
export async function handleRedirectRequest(req, res, { context, redirects, }) {
for (let redirect of redirects) {
if (redirect.source === req.originalUrl) {
// Log redirect
log(redirect.source, redirect.destination);
res.status(redirect.permanent ? 301 : 302);
return res.redirect(redirect.destination);
}
}
// Handle redirects from loader functions
if (context instanceof Response) {
const status = context.status; // "status" is only available when redirecting from loader, normally it's statusCode
if (status === 302 || status === 301) {
const redirectURL = context.headers.get('Location');
// Set redirect status
res.status(status);
// Log redirect
log(req.originalUrl, redirectURL);
// Redirect
return res.redirect(redirectURL);
}
// TODO: Check this line again
return await sendRasenganResponse(res, context);
}
}
export async function handleDocumentRequest(req, res, runner, options) {
try {
const { __dirname, config, handler } = options;
// Get the render function and app router
const { render } = await runner.import(join(`${__dirname}./../../entries/server/entry.server.js`));
// Create rasengan request for static routing
let request = createRasenganRequest(req, res);
let context = await handler.query(request);
// Handle redirects from config file
const redirects = await config.redirects();
const redirectFound = await isStaticRedirectFromConfig(req, redirects);
if (isRedirectResponse(context) || redirectFound) {
return await handleRedirectRequest(req, res, { context, redirects });
}
if (!(context instanceof Response)) {
// Extract meta from context
const metadata = extractMetaFromRRContext(context);
// Create static router
let router = createStaticRouter(handler.dataRoutes, context);
const headers = extractHeadersFromRRContext(context);
// Set headers
res.writeHead(context.statusCode, {
...Object.fromEntries(headers),
});
const Router = _jsx(StaticRouterProvider, { router: router, context: context });
// If stream mode enabled, render the page as a plain text
return await render(Router, res, {
metadata,
});
}
return context;
}
catch (error) {
// Just log the error for now
console.error(error);
}
}
export async function handleDataRequest(request, handler) {
// 1. we don't want to proxy the browser request directly to our router, so we
// make a new one.
let newRequest = request.method === 'POST'
? new Request(request.url, {
method: request.method,
headers: createRasenganHeaders(request.headers),
// @ts-expect-error this is valid, types are wrong
body: new URLSearchParams(await request.formData()),
})
: new Request(request.url, {
headers: createRasenganHeaders(request.headers),
});
// 2. get data from our router, queryRoute knows to call the action or loader
// of the leaf route that matches
let data = await handler.queryRoute(newRequest);
// 3. send the response
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}
export async function handleSpaModeRequest(res, runner, options) {
try {
// Import Template
const Template = (await runner.import(`${options.rootPath}/src/template`))
.default;
// Convert TemplateLayout to string
const html = renderToString(_jsx(TemplateLayout, { Template: Template, isSpaMode: true }));
// Set status code
res.status(200);
// Set headers
res.setHeader('Content-Type', 'text/html');
// Send response
return res.send(html);
}
catch (error) {
console.error(error);
// Set status code
res.status(500);
// Set headers
res.setHeader('Content-Type', 'text/html');
// Send response
return res.send(`
<h1>Internal Server Error</h1>
<p>Something went wrong</p>
`);
}
}