@bonniernews/local-esi

    2.1.1 • Public • Published

    Local-ESI

    Built latest

    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 stream
    • HTMLWriter: transform class that returns markup from object stream
    • parse: 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 cookies
      • headers: request headers, accessible through ESI globals HTTP_<HEADER_NAME>, x-forwarded-for will be accessible as REMOTE_ADDR
      • cookies: object with request cookies, accessible through ESI global HTTP_COOKIE
      • path: string request path, mapped to ESI global REQUEST_PATH
      • query: object request query parameters, accessible through ESI global QUERY_STRING
      • localhost: host to use when a relative src is used by eval or include, defaults to headers.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 parse
    • options: same as for for ESI

    Returns promise:

    • body: string with ESI evaluated markup or body from $set_response_code
    • statusCode: occasional status code from $set_response_code or $set_redirect
    • headers: object with added headers (in lowercase) from $add_header or $set_redirect(location), NB! set-cookie will be in a list

    Example express route:

    "use strict";
    
    const HTMLParser = require("@bonniernews/atlas-html-stream");
    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(response.statusCode, headers.location);
      }
    
      res.status(statusCode || 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 code
    • body: optional string body

    add_header

    Parser encountered a $add_header instruction with HTTP header name and value.

    Signature:

    • name: HTTP header name
    • value: HTTP header value

    set_redirect

    Parser encountered a $set_redirect instruction with optional status code and location.

    Signature:

    • statusCode: redirect HTTP status code
    • location: 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.

    Keywords

    Install

    npm i @bonniernews/local-esi

    DownloadsWeekly Downloads

    296

    Version

    2.1.1

    License

    MIT

    Unpacked Size

    53.3 kB

    Total Files

    17

    Last publish

    Collaborators

    • expgripen
    • andolf
    • markusn
    • linuss
    • joelabrahamsson
    • paed01
    • jonaswalden
    • indeedshouts
    • marcusgronblad