neweb
Version:
[![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage percentage][coveralls-image]][coveralls-url] [ • 4.32 kB
text/typescript
import { Request, Response } from "express";
import { NewebGlobalStore } from "./..";
import PageRenderer from "./PageRenderer";
import { createSeance, loadSeancePage } from "./seances";
import { enrichResponseForSession, getSessionContext, resolveSessionIdByRequest } from "./sessions";
export async function onHttpRequest(store: NewebGlobalStore, req: Request, response: Response) {
const requestId = (+new Date()).toString() + Math.floor(Math.random() * 10000).toString();
await store.setObject("http-request", requestId, {
type: "object",
objectType: "app",
id: "default",
}, req);
await store.setObject("http-response", requestId, {
type: "object",
objectType: "app",
id: "default",
}, response);
const request = {
cookies: req.cookies || {},
headers: req.headers || {},
hostname: req.hostname,
url: req.url,
clientIpAddress: req.ip,
};
await store.create("request", requestId, {
type: "object",
objectType: "http-request",
id: requestId,
}, request);
await onRequest(store, requestId);
}
/**
* Схема работы:
* Получаем контекст сессии, который нужен для работы роутера
* Создаем новый класс роутера, передаем в него запрос и ждем, когда появится маршрут
* Очищаем роутер, он больше не понадобится
* Если тип маршрута - NotFound или Redirect, то посылаем соответствующий ответ клиенту (404 или 302)
* Создаем новый сеанс (Seans) и загружаем в него страницу, ждем формирования страницы
* С помощью серверного рендеринга получаем код страницы в виде html-строки
* Заполняем шаблон ответа кодом страницы, мета-информацией и информацией о сеансе
* Отправляем ответ клиенту
*/
export async function onRequest(store: NewebGlobalStore, requestId: string) {
const request = await store.get("request", requestId);
// get session's context
const sessionId = await resolveSessionIdByRequest(store, request);
const sesionContext = await getSessionContext(store, {
type: "data",
dataType: "request",
id: requestId,
}, sessionId);
const app = await store.getObject("app", "default");
// get current route
const RouterClass = await app.getRouterClass();
const router = new RouterClass({
context: await app.getContext(),
session: sesionContext,
request,
});
router.navigate({ request });
const route = await router.waitRoute();
router.dispose();
// Handling route
const res = await store.getObject("http-response", requestId);
// Handling route
if (route.type === "redirect") {
res.header("location", route.url);
res.sendStatus(302);
return;
}
if (route.type === "notFound") {
res.status(404).send(route.text);
return;
}
// handling route of page
// create new seans with RoutePage
const seanceId = await createSeance(store, { sessionId, request });
await loadSeancePage(store, seanceId, route.page);
// get info about seance
const seanceDump = {
seanceId,
page: await store.get("seance-current-page", seanceId),
};
const page = seanceDump.page;
// render page on server
const pageRenderer = new PageRenderer({
app,
});
const { html } = await pageRenderer.render(seanceDump.page);
const filledHtml = await app.fillTemplate(html,
{ title: page.title, meta: page.meta }, seanceDump);
// Add session info to response
await enrichResponseForSession(store, sessionId, res);
// send html and seans'es info to client
res.status(200).send(filledHtml);
await store.removeObject("http-request", requestId);
await store.removeObject("http-response", requestId);
}