Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@bonniernews/local-esi

Package Overview
Dependencies
Maintainers
6
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bonniernews/local-esi - npm Package Compare versions

Comparing version 0.14.0 to 1.0.0

lib/ESIEvaluator.js

80

index.js
"use strict";
const transformHtml = require("./lib/transformHtml");
const ESIListener = require("./lib/ESIListener");
const ESIEvaluator = require("./lib/ESIEvaluator");
const ListenerContext = require("./lib/ListenerContext");
const {asStream, transform, createESIParser} = require("./lib/transformHtml");
const redirectCodes = [301, 302, 303, 307, 308];
module.exports = localEsi;
module.exports.createStream = streaming;
module.exports.createParser = createParser;
module.exports.htmlWriter = require("./lib/htmlWriter");
function localEsi(html, req, res, next) {
const context = ListenerContext(req, res);
const listener = ESIListener(context);
transformHtml(html, listener, (err, parsed) => {
const context = ListenerContext(req);
let completed = false;
context.on("set_response_code", (statusCode, body) => {
completed = true;
res.status(statusCode).send(body === undefined ? "" : body);
});
context.on("add_header", (name, value) => {
res.set(name, value);
});
context.once("set_redirect", (statusCode, location) => {
completed = true;
res.redirect(location);
});
const listener = ESIEvaluator(context);
return transform(html, listener, (err, parsed) => {
if (err) return next(err);
if (context.redirected) {
return;
}
if (context.replacement) {
return res.send(context.replacement);
}
res.send(parsed);
if (!completed) res.send(parsed);
// return next && next(null, parsed);
});
}
module.exports = localEsi;
function streaming(req) {
const context = ListenerContext(req);
const listener = ESIEvaluator(context);
const pipeline = asStream(listener);
context.emitter = pipeline;
let responseCode;
const headers = {};
pipeline.once("set_response_code", onResponseCode);
pipeline.once("add_header", onAddHeader);
pipeline.once("set_redirect", close);
return pipeline;
function onResponseCode(int, body) {
responseCode = int;
if (int > 399 || body) return close();
if (headers.location && redirectCodes.includes(int)) pipeline.emit("set_redirect", responseCode, headers.location);
}
function onAddHeader(name, value) {
const headerName = name.toLowerCase();
headers[headerName] = value;
if (headerName === "location" && redirectCodes.includes(responseCode)) pipeline.emit("set_redirect", responseCode, value);
}
function close() {
pipeline.removeListener("set_response_code", onResponseCode);
pipeline.removeListener("add_header", onAddHeader);
pipeline.removeListener("set_redirect", close);
pipeline.destroy();
}
}
function createParser(req) {
const context = ListenerContext(req);
const listener = ESIEvaluator(context);
return createESIParser(listener);
}

20

lib/evaluateExpression.js

@@ -0,1 +1,2 @@

/* eslint-disable camelcase */
"use strict";

@@ -18,3 +19,2 @@ const esiExpressionParser = require("./esiExpressionParser");

},
// eslint-disable-next-line camelcase
base64_decode([arg]) {

@@ -27,3 +27,2 @@ const string = getFunc(arg.type)(arg);

},
// eslint-disable-next-line camelcase
base64_encode([arg]) {

@@ -36,3 +35,2 @@ const string = getFunc(arg.type)(arg);

},
// eslint-disable-next-line camelcase
url_encode([arg]) {

@@ -45,14 +43,15 @@ const string = getFunc(arg.type)(arg);

},
// eslint-disable-next-line camelcase
add_header([name, value]) {
context.res.set(getFunc(name.type)(name), getFunc(value.type)(value));
context.emit("add_header", getFunc(name.type)(name), getFunc(value.type)(value));
},
// eslint-disable-next-line camelcase
set_redirect([location]) {
context.res.redirect(getFunc(location.type)(location));
context.emit("set_redirect", 302, getFunc(location.type)(location));
context.redirected = true;
},
// eslint-disable-next-line camelcase
set_response_code([code]) {
context.res.status(getFunc(code.type)(code));
set_response_code([code, body]) {
if (body) {
return context.emit("set_response_code", getFunc(code.type)(code), getFunc(body.type)(body));
}
context.emit("set_response_code", getFunc(code.type)(code));
},

@@ -87,3 +86,2 @@ substr([arg1, arg2, arg3]) {

},
// eslint-disable-next-line camelcase
http_time([seconds]) {

@@ -90,0 +88,0 @@ const secondsInt = parseInt(getFunc(seconds.type)(seconds));

"use strict";
module.exports = function ListenerContext(req, res) {
const {EventEmitter} = require("events");
module.exports = function ListenerContext(req, res, emitter) {
const buildHeaderVariables = (headers) => {

@@ -14,3 +15,5 @@ if (!headers) return {};

return {
emitter = emitter || new EventEmitter();
const context = {
assigns: Object.assign(buildHeaderVariables(req && req.headers), {

@@ -31,3 +34,20 @@ "HTTP_COOKIE": req.cookies || {},

tags: [],
get emitter() {
return emitter;
},
set emitter(value) {
emitter = value;
},
on(...args) {
emitter.on(...args);
},
once(...args) {
emitter.once(...args);
},
emit(...args) {
emitter.emit(...args);
}
};
return context;
};
"use strict";
const HtmlParser = require("atlas-html-stream");
const {Readable, Transform} = require("stream");
const ESIParser = require("./ESIParser");
const pump = require("pump"); // replace with stream.pipeline when upping to node 10
const pumpify = require("pumpify");
const {Readable} = require("stream");
const htmlWriter = require("./htmlWriter");
class HtmlTransformer extends Transform {
constructor(filter, options) {
options = Object.assign({}, options, {objectMode: true});
super(options);
this.filter = filter;
}
module.exports = {
transform,
asStream,
convert,
createESIParser,
};
_transform(obj, encoding, next) {
const self = this;
this.filter(obj, (err, chunk) => {
if (err) return next(err);
if (chunk) self.push(chunk);
next();
});
}
}
module.exports = function parse(html, {onopentag, ontext, onclosetag}, onFinish) {
function transform(html, listener, onFinish) {
const bufferStream = convert(html);
const htmlParser = new HtmlParser({ preserveWS: true });
const transform = new HtmlTransformer(filter);
return new Promise((resolve, reject) => {
let data = "";
bufferStream.pipe(htmlParser).pipe(transform)
.once("error", (err) => (onFinish || reject)(err))
.on("data", (chunk) => {
data += chunk;
})
.on("finish", () => {
if (onFinish) onFinish(null, data);
resolve(data);
});
pump(bufferStream, asStream(listener), htmlWriter(), (err) => {
if (onFinish) {
onFinish(err, data);
return resolve();
}
if (err) return reject(err);
resolve(data);
}).on("data", (chunk) => {
data += chunk;
});
});
}
function filter({name, data, text}, next) {
if (text) {
return ontext(text, next);
} else if (name && data) {
return onopentag(name, data, next);
} else {
return onclosetag(name, next);
}
}
};
function asStream(listener) {
const htmlParser = new HtmlParser({ preserveWS: true });
const esiParser = createESIParser(listener);
return pumpify.obj(htmlParser, esiParser);
}

@@ -78,1 +65,15 @@ function convert(buf, chunkSize) {

}
function createESIParser({onopentag, ontext, onclosetag}) {
return new ESIParser(filter);
function filter({name, data, text}, next) {
if (text) {
return ontext(text, next);
} else if (name && data) {
return onopentag(name, data, next);
} else {
return onclosetag(name, next);
}
}
}
{
"name": "@bonniernews/local-esi",
"version": "0.14.0",
"version": "1.0.0",
"description": "Local Edge Side Includes parser",

@@ -16,4 +16,5 @@ "main": "index.js",

"chai": "^4.2.0",
"eslint": "^6.4.0",
"mocha": "^6.2.0",
"chronokinesis": "^2.0.1",
"eslint": "^6.5.1",
"mocha": "^6.2.1",
"nock": "^11.3.5"

@@ -23,3 +24,4 @@ },

"atlas-html-stream": "^1.2.0",
"chronokinesis": "^2.0.1",
"pump": "^3.0.0",
"pumpify": "^2.0.0",
"request": "^2.88.0"

@@ -26,0 +28,0 @@ },

@@ -8,4 +8,9 @@ Local-ESI

# Example Express route:
# API
- `localEsi(req, res[, callback])`: returns ESI evaluated markup in callback or as promised
- `localEsi.createStream(req)`: returns pipable object stream with ESI evaluated content
## `localEsi(req, res[, callback])`
```javascript

@@ -24,1 +29,26 @@ "use strict";

```
## `localEsi.createStream(req[, res])`
Used as object stream.
```javascript
"use strict";
const localEsi = require("@bonniernews/local-esi");
module.exports = (req, res, next) => {
const esiPipeline = localEsi.createStream(req);
res.render("index", { data: "a" })
.pipe(esiPipeline)
.on("error", next)
.on("set_redirect", (statusCode, location) => res.redirect(statusCode, location));
};
```
## Events
- `error`: an error occured
- `set_response_code`: send status code and optional body
- `add_header`: set header name and value
- `set_redirect`: redirect with status code and location
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc