Skip to content
This repository was archived by the owner on Oct 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [2.3.0] - 2019-07-28
### Added
- Support for custom templates
- Request object is now passed to `enrichCustomParams` function

### Fixed
- PXHD cookie will not echo back from client

## [2.2.1] - 2019-05-24
### Added
- fixed timeout error, lint fixes
- fixed timeout error, lint fixes
- removed node 11 from tests because it turned EOL

### Fixed
- pxhd cookie not been sent in block activity
- Do not echo back pxhd cookie coming from client
- set pxhd expiration


## [2.2.0] - 2019-05-06
### Added
- Send telemetry by command
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[PerimeterX](http://www.perimeterx.com) Shared base for NodeJS enforcers
=============================================================

> Latest stable version: [v2.2.1](https://www.npmjs.com/package/perimeterx-node-core)
> Latest stable version: [v2.3.0](https://www.npmjs.com/package/perimeterx-node-core)

This is a shared base implementation for PerimeterX Express enforcer and future NodeJS enforcers. For a fully functioning implementation example, see the [Node-Express enforcer](https://github.com/PerimeterX/perimeterx-node-express/) implementation.

Expand Down
6 changes: 3 additions & 3 deletions lib/pxapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function callServer(ctx, config, callback) {
const ip = ctx.ip;
const fullUrl = ctx.fullUrl;
const vid = ctx.vid || '';
const pxhd = ctx.pxhd || '';
const pxhd = ctx.pxhdClient || '';
const vidSource = ctx.vidSource || '';
const uuid = ctx.uuid || '';
const uri = ctx.uri || '/';
Expand Down Expand Up @@ -49,7 +49,7 @@ function callServer(ctx, config, callback) {
data.additional.px_cookie = JSON.stringify(ctx.decodedCookie);
}

pxUtil.prepareCustomParams(config, data.additional);
pxUtil.prepareCustomParams(config, data.additional, ctx.originalRequest);

const reqHeaders = {
Authorization: 'Bearer ' + config.AUTH_TOKEN,
Expand Down Expand Up @@ -117,7 +117,7 @@ function evalByServerCall(ctx, config, callback) {
ctx.passReason = config.PASS_REASON.REQUEST_FAILED;
return callback(config.SCORE_EVALUATE_ACTION.UNEXPECTED_RESULT);
}
ctx.pxhd = res.pxhd;
ctx.pxhdServer = res.pxhd;
const action = isBadRiskScore(res, ctx, config);
/* score response invalid - pass traffic */
if (action === -1) {
Expand Down
6 changes: 3 additions & 3 deletions lib/pxclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ class PxClient {
if (ctx.vid) {
pxData.vid = ctx.vid;
}
if (ctx.pxhd && (activityType === 'page_requested') || activityType === 'block') {
pxData.pxhd = ctx.pxhd;
pxUtil.prepareCustomParams(config, details);
if (ctx.pxhdClient && (activityType === 'page_requested' || activityType === 'block')) {
pxData.pxhd = ctx.pxhdClient;
pxUtil.prepareCustomParams(config, details, ctx.originalRequest);
}
pxData.details = details;

Expand Down
8 changes: 5 additions & 3 deletions lib/pxconfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class PxConfig {
['CSS_REF', 'cssRef'], ['CUSTOM_LOGO', 'customLogo'], ['SENSITIVE_ROUTES', 'sensitiveRoutes'], ['WHITELIST_ROUTES', 'whitelistRoutes'], ['DYNAMIC_CONFIGURATIONS', 'dynamicConfigurations'],
['MODULE_MODE', 'moduleMode'], ['FIRST_PARTY_ENABLED', 'firstPartyEnabled'], ['ADDITIONAL_ACTIVITY_HANDLER', 'additionalActivityHandler'], ['ENRICH_CUSTOM_PARAMETERS', 'enrichCustomParameters'],
['TESTING_MODE', 'testingMode'], ['WHITELIST_EXT', 'whitelistExt'], ['BYPASS_MONITOR_HEADER', 'bypassMonitorHeader'], ['ADVANCED_BLOCKING_RESPONSE', 'advancedBlockingResponse'],
['TELEMETRY_COMMAND_HEADER', 'telemetryCommandHeader']];
['TELEMETRY_COMMAND_HEADER', 'telemetryCommandHeader'], ['CUSTOM_TEMPLATE_ROOT', 'customTemplateRoot'], ['CUSTOM_TEMPLATE_DATA', 'customTemplateData']];

configKeyMapping.forEach(([targetKey, sourceKey]) => {
this.PX_DEFAULT[targetKey] = PxConfig.configurationsOverriding(this.PX_DEFAULT, params, targetKey, sourceKey);
Expand All @@ -56,7 +56,7 @@ class PxConfig {
}
const fileMappedConfig = {};
for (const key in fileConfig) {
if (configSchemaMapper.hasOwnProperty(key)) {
if (Object.prototype.hasOwnProperty.call(configSchemaMapper, key)) {
fileMappedConfig[configSchemaMapper[key]] = fileConfig[key];
} else {
this.logger.debug(`config key ${key} is not mapped, ignoring it`);
Expand Down Expand Up @@ -208,7 +208,9 @@ function pxDefaultConfig(PX_INTERNAL) {
WHITELIST_EXT: [],
BYPASS_MONITOR_HEADER: '',
CONFIG_PATH: '',
ADVANCED_BLOCKING_RESPONSE: true
ADVANCED_BLOCKING_RESPONSE: true,
CUSTOM_TEMPLATE_ROOT: '',
CUSTOM_TEMPLATE_DATA: {}
};
}

Expand Down
3 changes: 2 additions & 1 deletion lib/pxcontext.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class PxContext {
this.userAgent = userAgent;
this.uri = req.originalUrl || '/';
this.fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
this.originalRequest = req.originalRequest;
this.httpVersion = req.httpVersion || '';
this.httpMethod = req.method || '';
this.sensitiveRoute = this.isSpecialRoute(config.SENSITIVE_ROUTES, this.uri);
Expand All @@ -34,7 +35,7 @@ class PxContext {
if (key.match(/^_px\d?$/)) {
this.cookies[key] = req.cookies[key];
} else if (key === '_pxhd') {
this.pxhd = req.cookies[key];
this.pxhdClient = req.cookies[key];
} else if ((key === '_pxvid' || key === 'pxvid') && vidRegex.test(req.cookies[key])) {
this.vid = req.cookies[key];
this.vidSource = 'vid_cookie';
Expand Down
9 changes: 5 additions & 4 deletions lib/pxenforcer.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ class PxEnforcer {
const verified = ctx.score < this._config.BLOCKING_SCORE;
if (res) {
const setCookie = res.getHeader('Set-Cookie') ? res.getHeader('Set-Cookie') : '';
const pxhdCookie = ctx.pxhd ? '_pxhd=' + ctx.pxhd : '';
const pxhdCookie = ctx.pxhdServer ? '_pxhd=' + ctx.pxhdServer : '';
const setCookieModified = [setCookie, pxhdCookie].filter(Boolean);
if (setCookieModified.length > 0) {
res.setHeader('Set-Cookie', setCookieModified);
res.setHeader('Set-Cookie', setCookieModified + ';expires=' + (new Date(new Date().setFullYear(new Date().getFullYear() + 1))));
}
}
// Handle async activities
Expand Down Expand Up @@ -329,14 +329,15 @@ class PxEnforcer {
hostUrl: hostUrl,
jsClientSrc: jsClientSrc,
firstPartyEnabled: this._config.FIRST_PARTY_ENABLED,
blockScript: captchaSrc
blockScript: captchaSrc,
customData: this._config.CUSTOM_TEMPLATE_DATA && JSON.stringify(this._config.CUSTOM_TEMPLATE_DATA)
};
}

compileMustache(template, props, cb) {
let htmlTemplate = '';

mu.root = `${__dirname}/templates`;
mu.root = this._config.CUSTOM_TEMPLATE_ROOT || `${__dirname}/templates`;
const compile = mu.compileAndRender(`${template}.mustache`, props);

// Building html from template into string variable
Expand Down
5 changes: 3 additions & 2 deletions lib/pxutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ function filterConfig(config) {
* it will populate to @dict with the proper custom params
* @param {pxconfig} config - The config object of the application
* @param {object} dict - the object that should be populated with the custom params
* @param {object} originalRequest - (optional) original request based on the calling framework
* */
function prepareCustomParams(config, dict) {
function prepareCustomParams(config, dict, originalRequest) {
const customParams = {
'custom_param1': '',
'custom_param2': '',
Expand All @@ -154,7 +155,7 @@ function prepareCustomParams(config, dict) {
'custom_param10': ''
};
if (config.ENRICH_CUSTOM_PARAMETERS) {
const enrichedCustomParams = config.ENRICH_CUSTOM_PARAMETERS(customParams);
const enrichedCustomParams = config.ENRICH_CUSTOM_PARAMETERS(customParams, originalRequest);
for (const param in enrichedCustomParams) {
if (param.match(/^custom_param([1-9]|10)$/) && enrichedCustomParams[param] !== '') {
dict[param] = enrichedCustomParams[param];
Expand Down
Loading