Git Product home page Git Product logo

local-esi's Introduction

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 {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.

local-esi's People

Contributors

andolf avatar izzyross avatar jesperzachrisson avatar jimmycallin avatar joelabrahamsson avatar jonaswalden avatar markusn avatar matsrorbecker avatar niklashagner avatar odynvolk avatar paed01 avatar sammi87 avatar sebastianqvarfordt avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.