@bonniernews/local-esi v3.0.1
Local-ESI
Make your Express app work like it had Akamai Edge Side Includes parsing or just stream your ESI decorated markup to the parser.
API
ESI: transform class that returns an ESI transform streamHTMLWriter: transform class that returns markup from object streamparse: async function that returns ESI evaluated markup
new ESI([options])
Create an ESI transform stream. Emits events.
Arguments:
options: optional options object with headers and cookiesheaders: request headers, accessible through ESI globalsHTTP_<HEADER_NAME>,x-forwarded-forwill be accessible asREMOTE_ADDRx-localesi-geo: headers to simulate Akamai's geo location abilities. Defaults to:country_code=SE,georegion=208. Accessible through ESI globalGEO{}
cookies: object with request cookies, accessible through ESI globalHTTP_COOKIEpath: string request path, mapped to ESI globalREQUEST_PATHquery: object request query parameters, accessible through ESI globalQUERY_STRINGlocalhost: host to use when a relative src is used by eval or include, defaults toheaders.host
Returns:
- esi evaluated object stream
Example express route:
"use strict";
const HTMLParser = require("@bonniernews/atlas-html-stream");
const {ESI, HTMLWriter} = require("@bonniernews/local-esi");
const {pipeline} = require("stream");
module.exports = function streamRender(req, res, next) {
const { headers, cookies, path, query } = req;
const options = {
headers,
cookies,
path,
query,
localhost: `localhost:${req.socket.server.address().port}`,
};
const esi = new ESI(options)
.once("set_redirect", function onSetRedirect(statusCode, location) {
res.status(statusCode).redirect(location);
this.destroy();
})
.on("set_response_code", function onSetResponseCode(statusCode, body) {
res.status(statusCode);
if (!body) return;
res.send(body);
this.destroy();
})
.on("add_header", (name, value) => {
res.set(name, value);
});
const body = "";
pipeline([
res.render("index"),
new HTMLParser({preserveWS: true}),
esi,
new HTMLWriter(),
], (err) => {
if (err?.code === "ERR_STREAM_PREMATURE_CLOSE"]) {
return;
} else if (err) {
return next(err);
}
return res.send(body);
}).on("data", (chunk) => {
body += chunk;
});
};parse(html, options)
Arguments:
html: markup to parseoptions: same as for for ESI
Returns promise:
body: string with ESI evaluated markup or body from$set_response_codestatusCode: occasional status code from$set_response_codeor$set_redirectheaders: object with added headers (in lowercase) from$add_headeror$set_redirect(location), NB!set-cookiewill be in a list
Example express route:
"use strict";
const {parse} = require("@bonniernews/local-esi");
module.exports = function render(req, res, next) {
const { headers, cookies, path, query } = req;
const options = {
headers,
cookies,
path,
query,
localhost: `localhost:${req.socket.server.address().port}`,
};
const html = res.render("index");
const {statusCode, headers, body} = await parse(html, options);
if (statusCode < 309 && statusCode > 300) {
return res.redirect(statusCode, headers.location);
}
if (statusCode) {
res.status(statusCode);
} else if (!res.statusCode) {
res.status(200);
}
return res.send(body);
};new HTMLWriter()
Returns transform object stream to markup buffer stream.
ESI Parsing Events
ESI instructions are emitted as events.
set_response_code
Parser encountered a $set_response_code instruction with status code and optional body.
Signature:
statusCode: number HTTP status codebody: optional string body
add_header
Parser encountered a $add_header instruction with HTTP header name and value.
Signature:
name: HTTP header namevalue: HTTP header value
set_redirect
Parser encountered a $set_redirect instruction with optional status code and location.
Signature:
statusCode: redirect HTTP status codelocation: redirect location
Markup object stream
Object streams requires the schema {name, data, text} representing tag name, tag attributes, and text. This project uses @bonniernews/atlas-html-stream for html parsing.
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago