Skip to content

Commit

Permalink
feat: support custom pathToRegexpModule
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Jan 22, 2025
1 parent 09fe2ae commit bdfa263
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 17 deletions.
11 changes: 7 additions & 4 deletions app/middleware/securities.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ module.exports = (_, app) => {
}

// format csrf.cookieDomain
const orginalCookieDomain = options.csrf.cookieDomain;
if (orginalCookieDomain && typeof orginalCookieDomain !== 'function') {
options.csrf.cookieDomain = () => orginalCookieDomain;
const originalCookieDomain = options.csrf.cookieDomain;
if (originalCookieDomain && typeof originalCookieDomain !== 'function') {
options.csrf.cookieDomain = () => originalCookieDomain;
}

defaultMiddleware.forEach(middlewareName => {
Expand Down Expand Up @@ -46,7 +46,10 @@ module.exports = (_, app) => {
app.deprecate('[egg-security] Please use `config.security.xframe.ignore` instead, `config.security.xframe.blackUrls` will be removed very soon');
opt.ignore = opt.blackUrls;
}
opt.matching = createMatch(opt);
opt.matching = createMatch({
...opt,
pathToRegexpModule: app.options.pathToRegexpModule,
});

const fn = require(path.join(__dirname, '../../lib/middlewares', middlewareName))(opt, app);
middlewares.push(fn);
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@eggjs/ip": "^2.0.2",
"csrf": "^3.0.6",
"delegates": "^1.0.0",
"egg-path-matching": "^1.0.0",
"egg-path-matching": "^1.2.0",
"escape-html": "^1.0.3",
"extend": "^3.0.1",
"koa-compose": "^4.1.0",
Expand All @@ -43,7 +43,8 @@
"eslint": "^8.40.0",
"eslint-config-egg": "^12.2.1",
"spy": "^1.0.0",
"supertest": "^6.3.3"
"supertest": "^6.3.3",
"path-to-regexp-v8": "npm:path-to-regexp@8"
},
"scripts": {
"lint": "eslint .",
Expand Down
20 changes: 20 additions & 0 deletions test/fixtures/apps/iframe-with-pathToRegexpModule/app/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = function(app) {
app.get('/', controller);
app.get('/foo', controller);
app.get('/hello', controller);
app.get('/hello/other/world', controller);
app.get('/world/12', controller);

app.get('/options', options, controller);

async function controller() {
this.body = 'body';
}

async function options(ctx, next) {
ctx.securityOptions.xframe = {
value: 'ALLOW-FROM http://www.domain.com',
};
return next();
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
exports.keys = 'test key';

exports.security = {
defaultMiddleware: 'xframe',
xframe: {
ignore: ['/hello', '/world/:id'],
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "iframe-with-pathToRegexpModule"
}
125 changes: 125 additions & 0 deletions test/xframe-with-pathToRegexpModule.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
const { strict: assert } = require('node:assert');
const mm = require('egg-mock');

describe('test/xframe-with-pathToRegexpModule.test.js', () => {
let app;
let app2;
let app3;
let app4;
before(async () => {
app = mm.app({
baseDir: 'apps/iframe-with-pathToRegexpModule',
plugin: 'security',
pathToRegexpModule: require.resolve('path-to-regexp-v8'),
});
await app.ready();

app2 = mm.app({
baseDir: 'apps/iframe-novalue',
plugin: 'security',
pathToRegexpModule: require.resolve('path-to-regexp-v8'),
});
await app2.ready();

app3 = mm.app({
baseDir: 'apps/iframe-allowfrom',
plugin: 'security',
pathToRegexpModule: require.resolve('path-to-regexp-v8'),
});
await app3.ready();

app4 = mm.app({
baseDir: 'apps/iframe-black-urls',
plugin: 'security',
pathToRegexpModule: require.resolve('path-to-regexp-v8'),
});
await app4.ready();
});

afterEach(mm.restore);

it('should contain X-Frame-Options: SAMEORIGIN', async () => {
await app.httpRequest()
.get('/')
.set('accept', 'text/html')
.expect('x-frame-options', 'SAMEORIGIN');

await app.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('x-frame-options', 'SAMEORIGIN');
});

it('should contain X-Frame-Options: ALLOW-FROM http://www.domain.com by this.securityOptions', async () => {
const res = await app.httpRequest()
.get('/options')
.set('accept', 'text/html');
assert.equal(res.status, 200);
assert.equal(res.headers['x-frame-options'], 'ALLOW-FROM http://www.domain.com');
});

it('should contain X-Frame-Options: SAMEORIGIN when dont set value option', function(done) {
app2.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('x-frame-options', 'SAMEORIGIN', done);
});

it('should contain X-Frame-Options: ALLOW-FROM with page when set ALLOW-FROM and page option', function(done) {
app3.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('x-frame-options', 'ALLOW-FROM http://www.domain.com', done);
});

it('should not contain X-Frame-Options: SAMEORIGIN when use ignore', async () => {
let res = await app.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

// '/hello' won't match '/hello/other/world' on path-to-regexp@8
res = await app.httpRequest()
.get('/hello/other/world')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], 'SAMEORIGIN');

res = await app4.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app.httpRequest()
.get('/world/12')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app.httpRequest()
.get('/world/12?xx=xx')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/world/12')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/world/12?xx=xx')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);
});
});
28 changes: 17 additions & 11 deletions test/xframe.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ describe('test/xframe.test.js', () => {
await app.httpRequest()
.get('/')
.set('accept', 'text/html')
.expect('X-Frame-Options', 'SAMEORIGIN');
.expect('x-frame-options', 'SAMEORIGIN');

await app.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('X-Frame-Options', 'SAMEORIGIN');
.expect('x-frame-options', 'SAMEORIGIN');
});

it('should contain X-Frame-Options: ALLOW-FROM http://www.domain.com by this.securityOptions', async () => {
Expand All @@ -58,57 +58,63 @@ describe('test/xframe.test.js', () => {
app2.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('X-Frame-Options', 'SAMEORIGIN', done);
.expect('x-frame-options', 'SAMEORIGIN', done);
});

it('should contain X-Frame-Options: ALLOW-FROM with page when set ALLOW-FROM and page option', function(done) {
app3.httpRequest()
.get('/foo')
.set('accept', 'text/html')
.expect('X-Frame-Options', 'ALLOW-FROM http://www.domain.com', done);
.expect('x-frame-options', 'ALLOW-FROM http://www.domain.com', done);
});

it('should not contain X-Frame-Options: SAMEORIGIN when use ignore', async () => {
let res = await app.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app.httpRequest()
.get('/hello/other/world')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app4.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app.httpRequest()
.get('/world/12')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app.httpRequest()
.get('/world/12?xx=xx')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/hello')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/world/12')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);

res = await app2.httpRequest()
.get('/world/12?xx=xx')
.set('accept', 'text/html')
.expect(200);
assert.equal(res.headers['X-Frame-Options'], undefined);
assert.equal(res.headers['x-frame-options'], undefined);
});
});

0 comments on commit bdfa263

Please sign in to comment.