Skip to content

Commit

Permalink
Merge pull request #76 from PerimeterX/dev
Browse files Browse the repository at this point in the history
[ADD] multi app support. (#75)
  • Loading branch information
ilaipx authored Mar 14, 2019
2 parents 0ff958f + 93d0af3 commit 8dfa09f
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 68 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ 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/).

## [6.0.0] - 2019-03-11
### Added
- Support multiple instances of the enforcer using the `new` method.

### Changed
- PxClient now requires a config as an argument for the init function.
- Updated perimeterx-node-core dependency to version ~2.0.0.

## [5.1.0] - 2019-02-25
### Added
- Support for testing blocking flow in monitor mode
Expand Down
46 changes: 45 additions & 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) Express.js Middleware
=============================================================

> Latest stable version: [v5.1.0](https://www.npmjs.com/package/perimeterx-node-express)
> Latest stable version: [v6.0.0](https://www.npmjs.com/package/perimeterx-node-express)
Table of Contents
-----------------
Expand All @@ -30,6 +30,7 @@ Table of Contents
* [Proxy Support](#proxySupport)
* [Test Block Flow on Monitoring Mode](#bypassMonitorHeader)
- [Advanced Blocking Response](#advancedBlockingResponse)
- [Multiple App Support](#multipleAppSupport)

## <a name="installation"></a> Installation
PerimeterX Express.js middleware is installed via NPM:
Expand Down Expand Up @@ -113,6 +114,7 @@ server.listen(8081, () => {
console.log('server started');
});
```

## <a name="upgrade"></a> Upgrading

To upgrade to the latest Enforcer version, run:
Expand Down Expand Up @@ -373,3 +375,45 @@ window._pxOnCaptchaSuccess = function(isValid) {

For details on how to create a custom Captcha page, refer to the [documentation](https://console.perimeterx.com/docs/server_integration_new.html#custom-captcha-section)

## <a name="multipleAppSupport"></a> Multiple App Support
If you use two different apps on the same node runtime, you can create two instances and use them on two routes:

```javascript
"use strict";

const express = require('express');
const perimeterx = require('perimeterx-node-express');

const server = express();

/* the px-module and parser need to be initialized before any route usage */
const pxConfig1 = {
pxAppId: 'PX_APP_ID_1',
cookieSecretKey: 'PX_COOKIE_ENCRYPTION_KEY',
authToken: 'PX_TOKEN_1'
};
const middlewareApp1 = perimeterx.new(pxConfig1).middleware;
const app1Router = express.Router();
app1Router.use(middlewareApp1);
app1Router.get('/hello', (req, res) => {
res.send('Hello from App1');
});
server.use('/app1', app1Router);

const pxConfig2 = {
pxAppId: 'PX_APP_ID_2',
cookieSecretKey: 'PX_COOKIE_ENCRYPTION_KEY',
authToken: 'PX_TOKEN_2'
};
const middlewareApp2 = perimeterx.new(pxConfig2).middleware;
const app2Router = express.Router();
app2Router.use(middlewareApp2);
app2Router.get('/app2', (req, res) => {
res.send('Hello from App2');
});
server.use('/app2', app1Router);

server.listen(8081, () => {
console.log('server started');
});
```
72 changes: 9 additions & 63 deletions lib/perimeterx.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,17 @@
'use strict';

const MODULE_VERSION = 'NodeJS Module v5.1.0';

const PxExpressClient = require('./pxclient');
const PxEnforcer = require('perimeterx-node-core').PxEnforcer;
const cookieParser = require('cookie-parser');
let enforcer;
const PerimeterXEnforcer = require('./pxenforcer');
let enforcer = null;

/**
* PerimeterX (http://www.perimeterx.com) NodeJS-Express SDK
* Version 1.0 Published 12 May 2016
*/
module.exports.init = initPXModule;
module.exports.middleware = pxMiddleware;
module.exports.enforcer = () => {return enforcer};

/**
* initPXModule - Initialize PerimeterX middleware.
*
* @param {object} params - Configurations object to extend and overwrite the default settings.
*
*/
function initPXModule(params) {
params.moduleVersion = MODULE_VERSION;
let pxClient = new PxExpressClient();
enforcer = new PxEnforcer(params, pxClient);
if (enforcer.config.conf.DYNAMIC_CONFIGURATIONS) {
setInterval(enforcer.config.confManager.loadData.bind(enforcer.config.confManager), enforcer.config.conf.CONFIGURATION_LOAD_INTERVAL);
}
}
module.exports.init = (params) => {
const instance = new PerimeterXEnforcer(params);
enforcer = instance.enforcer;
module.exports.middleware = instance.middleware;
};
module.exports.enforcer = () => enforcer;

function parseCookies(req, res) {
return new Promise((resolve, reject) => {
if (!req.cookies) {
cookieParser()(req, res, () => {
resolve();
});
} else {
resolve();
}
});
}

/**
* pxMiddleware - middleware wrapper to score verification.
*
* @param {Object} req - HTTP Request.
* @param {Object} res - HTTP Response.
* @param {Function} next - callback function.
*/
function pxMiddleware(req, res, next) {
parseCookies(req, res).then(() => {
enforcer.enforce(req, res, (err, response) => {
if (!err && response) { //block
res.status(response.status);
if (response.header) {
res.setHeader(response.header.key, response.header.value);
}
if (response.headers) {
for (let header in response.headers) {
res.setHeader(header, response.headers[header]);
}
}
res.send(response.body);
} else { //pass
next();
}
});
});
}
module.exports.new = (params) => new PerimeterXEnforcer(params);
4 changes: 2 additions & 2 deletions lib/pxclient.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const PxClient = require('perimeterx-node-core').PxClient;

class PxExpressClient extends PxClient {
init() {
init(config) {
setInterval(() => {
this.submitActivities();
this.submitActivities(config);
}, 1000);
}
}
Expand Down
74 changes: 74 additions & 0 deletions lib/pxenforcer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const MODULE_VERSION = 'NodeJS Module v6.0.0';
const PxExpressClient = require('./pxclient');
const PxEnforcer = require('perimeterx-node-core').PxEnforcer;
const cookieParser = require('cookie-parser');

function parseCookies(req, res) {
return new Promise((resolve, reject) => {
if (!req.cookies) {
cookieParser()(req, res, () => {
resolve();
});
} else {
resolve();
}
});
}

class PerimeterXEnforcer {
/**
* @param {object} params - Configurations object to extend and overwrite the default settings
*/
constructor(params) {
params.moduleVersion = MODULE_VERSION;
let pxClient = new PxExpressClient();
this.enforcer = new PxEnforcer(params, pxClient);

if (this.enforcer.config.conf.DYNAMIC_CONFIGURATIONS) {
setInterval(
this.enforcer.config.confManager.loadData.bind(this.enforcer.config.confManager),
this.enforcer.config.conf.CONFIGURATION_LOAD_INTERVAL
);
}

this.middleware = this.newMiddleware();
}

newMiddleware() {
const enforcer = this.enforcer;
/**
* pxMiddleware - middleware wrapper to score verification.
*
* @param {Object} req - HTTP Request.
* @param {Object} res - HTTP Response.
* @param {Function} next - callback function.
*/
function pxMiddleware(req, res, next) {
parseCookies(req, res).then(() => {
enforcer.enforce(req, res, (err, response) => {
if (!err && response) { //block
res.status(response.status);
if (response.header) {
res.setHeader(response.header.key, response.header.value);
}

if (response.headers) {
for (let header in response.headers) {
if (response.headers.hasOwnProperty(header)) {
res.setHeader(header, response.headers[header]);
}
}
}
res.send(response.body);
} else { //pass
next();
}
});
});
}

return pxMiddleware;
}
}

module.exports = PerimeterXEnforcer;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "perimeterx-node-express",
"version": "5.1.0",
"version": "6.0.0",
"description": "PerimeterX Express.js middleware to monitor and block traffic according to PerimeterX risk score",
"main": "index.js",
"directories": {
Expand Down Expand Up @@ -30,7 +30,7 @@
"dependencies": {
"cookie-parser": "^1.4.1",
"moment": "^2.19.3",
"perimeterx-node-core": "~1.8.0"
"perimeterx-node-core": "~2.0.0"
},
"devDependencies": {
"express": "4.16.2",
Expand Down

0 comments on commit 8dfa09f

Please sign in to comment.