+import { initializeSite, isAuthPath } from "@utils/app";
+import { getHttpBaseInternal } from "@utils/env";
+import { ErrorPageData } from "@utils/types";
+import * as cookie from "cookie";
+import fetch from "cross-fetch";
import type { Request, Response } from "express";
import { StaticRouter, matchPath } from "inferno-router";
import { renderToString } from "inferno-server";
-import IsomorphicCookie from "isomorphic-cookie";
import { GetSite, GetSiteResponse, LemmyHttp } from "lemmy-js-client";
import { App } from "../../shared/components/app/app";
-import { getHttpBaseInternal } from "../../shared/env";
import {
InitialFetchRequest,
IsoDataOptionalSite,
+ RouteData,
} from "../../shared/interfaces";
import { routes } from "../../shared/routes";
-import { RequestState, wrapClient } from "../../shared/services/HttpService";
-import { ErrorPageData, initializeSite, isAuthPath } from "../../shared/utils";
+import {
+ FailedRequestState,
+ wrapClient,
+} from "../../shared/services/HttpService";
import { createSsrHtml } from "../utils/create-ssr-html";
import { getErrorPageData } from "../utils/get-error-page-data";
import { setForwardedHeaders } from "../utils/set-forwarded-headers";
export default async (req: Request, res: Response) => {
try {
const activeRoute = routes.find(route => matchPath(req.path, route));
- let auth: string | undefined = IsomorphicCookie.load("jwt", req);
+
+ let auth = req.headers.cookie
+ ? cookie.parse(req.headers.cookie).jwt
+ : undefined;
const getSiteForm: GetSite = { auth };
const headers = setForwardedHeaders(req.headers);
- const client = wrapClient(new LemmyHttp(getHttpBaseInternal(), headers));
+
+ const client = wrapClient(
+ new LemmyHttp(getHttpBaseInternal(), { fetchFunction: fetch, headers })
+ );
const { path, url, query } = req;
// This bypasses errors, so that the client can hit the error on its own,
// in order to remove the jwt on the browser. Necessary for wrong jwts
let site: GetSiteResponse | undefined = undefined;
- const routeData: RequestState<any>[] = [];
+ let routeData: RouteData = {};
let errorPageData: ErrorPageData | undefined = undefined;
let try_site = await client.getSite(getSiteForm);
- if (try_site.state === "failed" && try_site.msg == "not_logged_in") {
+
+ if (try_site.state === "failed" && try_site.msg === "not_logged_in") {
console.error(
"Incorrect JWT token, skipping auth so frontend can remove jwt cookie"
);
return res.redirect("/setup");
}
- if (site) {
+ if (site && activeRoute?.fetchInitialData) {
const initialFetchReq: InitialFetchRequest = {
client,
auth,
site,
};
- if (activeRoute?.fetchInitialData) {
- routeData.push(
- ...(await Promise.all([
- ...activeRoute.fetchInitialData(initialFetchReq),
- ]))
- );
- }
+ routeData = await activeRoute.fetchInitialData(initialFetchReq);
+ }
+
+ if (!activeRoute) {
+ res.status(404);
}
} else if (try_site.state === "failed") {
+ res.status(500);
errorPageData = getErrorPageData(new Error(try_site.msg), site);
}
+ const error = Object.values(routeData).find(
+ res => res.state === "failed" && res.msg !== "couldnt_find_object" // TODO: find a better way of handling errors
+ ) as FailedRequestState | undefined;
+
// Redirect to the 404 if there's an API error
- if (routeData[0] && routeData[0].state === "failed") {
- const error = routeData[0].msg;
- console.error(error);
- if (error === "instance_is_private") {
+ if (error) {
+ console.error(error.msg);
+
+ if (error.msg === "instance_is_private") {
return res.redirect(`/signup`);
} else {
- errorPageData = getErrorPageData(new Error(error), site);
+ res.status(500);
+ errorPageData = getErrorPageData(new Error(error.msg), site);
}
}
const wrapper = (
<StaticRouter location={url} context={isoData}>
- <App />
+ <App user={site?.my_user} />
</StaticRouter>
);
const root = renderToString(wrapper);
- res.send(await createSsrHtml(root, isoData));
+ res.send(await createSsrHtml(root, isoData, res.locals.cspNonce));
} catch (err) {
// If an error is caught here, the error page couldn't even be rendered
console.error(err);
res.statusCode = 500;
+
return res.send(
process.env.NODE_ENV === "development" ? err.message : "Server error"
);