diff --git a/lib/config.js b/lib/config.js index 14366569e2..2e4b3bb2b6 100644 --- a/lib/config.js +++ b/lib/config.js @@ -60,4 +60,6 @@ module.exports = { host: process.env.PROXY_HOST || null, port: process.env.PROXY_PORT || null, }, + blacklist: process.env.BLACKLIST && process.env.BLACKLIST.split(','), + whitelist: process.env.WHITELIST && process.env.WHITELIST.split(','), }; diff --git a/lib/index.js b/lib/index.js index 35045957f2..f97315be9e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -125,15 +125,16 @@ app.use(mount('/protected', protected_router.routes())).use(protected_router.all app.use(mount('/api', api_router.routes())).use(api_router.allowedMethods()); // connect +let server; if (config.connect.port) { - app.listen(config.connect.port, parseInt(config.listenInaddrAny) ? null : '127.0.0.1'); + server = app.listen(config.connect.port, parseInt(config.listenInaddrAny) ? null : '127.0.0.1'); logger.info('Listening Port ' + config.connect.port); } if (config.connect.socket) { if (fs.existsSync(config.connect.socket)) { fs.unlinkSync(config.connect.socket); } - app.listen(config.connect.socket, parseInt(config.listenInaddrAny) ? null : '127.0.0.1'); + server = app.listen(config.connect.socket, parseInt(config.listenInaddrAny) ? null : '127.0.0.1'); logger.info('Listening Unix Socket ' + config.connect.socket); process.on('SIGINT', () => { fs.unlinkSync(config.connect.socket); @@ -141,4 +142,7 @@ if (config.connect.socket) { }); } -module.exports = app; +module.exports = { + server: server, + app: app, +}; diff --git a/lib/middleware/access-control.js b/lib/middleware/access-control.js index 9cae1ce551..11c5280ab6 100644 --- a/lib/middleware/access-control.js +++ b/lib/middleware/access-control.js @@ -1,7 +1,6 @@ const art = require('art-template'); const path = require('path'); -const blacklist = process.env.BLACKLIST && process.env.BLACKLIST.split(','); -const whitelist = process.env.WHITELIST && process.env.WHITELIST.split(','); +const config = require('../config'); const reject = (ctx) => { ctx.response.status = 403; @@ -21,13 +20,13 @@ module.exports = async (ctx, next) => { if (requestPath === '/') { await next(); } else { - if (whitelist) { - if (!(whitelist.indexOf(ip) !== -1 || whitelist.indexOf(requestPath) !== -1)) { + if (config.whitelist) { + if (!(config.whitelist.indexOf(ip) !== -1 || config.whitelist.indexOf(requestPath) !== -1)) { reject(ctx); } } else { - if (blacklist) { - if (blacklist.indexOf(ip) !== -1 || blacklist.indexOf(requestPath) !== -1) { + if (config.blacklist) { + if (config.blacklist.indexOf(ip) !== -1 || config.blacklist.indexOf(requestPath) !== -1) { reject(ctx); } } diff --git a/lib/router.js b/lib/router.js index 6bc43d4f15..40b41efd13 100644 --- a/lib/router.js +++ b/lib/router.js @@ -86,23 +86,22 @@ router.get('/', async (ctx) => { }); }); -router.get('/test', (ctx) => { +router.get('/test/:id', (ctx) => { ctx.state.data = { - title: 'DIYgod', - link: 'https://diygod.me/', - description: '测试路由 Test route', + title: `Test ${ctx.params.id}`, + link: 'https://github.com/DIYgod/RSSHub', item: [ { title: 'Title1', description: 'Item1', pubDate: new Date('2018-4-2').toUTCString(), - link: 'https://diygod.me/1', + link: 'https://github.com/DIYgod/RSSHub/issues/1', }, { title: 'Title2', description: 'Item2', pubDate: new Date('2018-4-10').toUTCString(), - link: 'https://diygod.me/2', + link: 'https://github.com/DIYgod/RSSHub/issues/2', }, ], }; diff --git a/test/middleware/access-control.js b/test/middleware/access-control.js new file mode 100644 index 0000000000..ac4335ab17 --- /dev/null +++ b/test/middleware/access-control.js @@ -0,0 +1,37 @@ +const supertest = require('supertest'); +const Parser = require('rss-parser'); +const parser = new Parser(); +let server; + +async function checkBlock(response) { + expect(response.status).toBe(403); + expect(await parser.parseString(response.text)).toMatchObject({ + items: [], + title: '没有访问权限. Access denied.', + }); +} + +afterEach(() => { + process.env.BLACKLIST = undefined; + server.close(); +}); + +describe('access-control', () => { + it(`blacklist`, async () => { + process.env.BLACKLIST = '/test/1,/test/2,233.233.233.233'; + server = require('../../lib/index').server; + const request = supertest(server); + + const response1 = await request.get('/test/1'); + checkBlock(response1); + + const response2 = await request.get('/test/2'); + checkBlock(response2); + + const response31 = await request.get('/test/3'); + expect(response31.status).toBe(200); + + const response32 = await request.get('/test/3').set('X-Forwarded-For', '233.233.233.233'); + checkBlock(response32); + }); +}); diff --git a/test/router.js b/test/router.js index aa23b2ab9b..40265f88dc 100644 --- a/test/router.js +++ b/test/router.js @@ -1,6 +1,6 @@ const supertest = require('supertest'); -const app = require('../lib/index'); -const request = supertest(app.callback()); +const { server } = require('../lib/index'); +const request = supertest(server); const Parser = require('rss-parser'); const parser = new Parser(); const config = require('../lib/config'); @@ -46,6 +46,10 @@ async function checkRSS(response) { }); } +afterAll(() => { + server.close(); +}); + describe('router', () => { // root it(`/`, async () => { @@ -56,14 +60,14 @@ describe('router', () => { }); // route - it(`/test (origin)`, async () => { - const response = await request.get('/test'); + it(`/test/1 (origin)`, async () => { + const response = await request.get('/test/1'); expect(response.status).toBe(200); await checkRSS(response); }); - it(`/test (cache)`, async () => { - const response = await request.get('/test'); + it(`/test/1 (cache)`, async () => { + const response = await request.get('/test/1'); expect(response.status).toBe(200); if (config.cacheType === 'memory') { expect(response.headers['x-koa-memory-cache']).toBe('true'); @@ -82,7 +86,7 @@ describe('router', () => { status: 0, data: { test: { - routes: ['/test'], + routes: ['/test/:id'], }, }, message: 'request returned 1 route', @@ -96,7 +100,7 @@ describe('router', () => { status: 0, data: { test: { - routes: ['/test'], + routes: ['/test/:id'], }, }, message: expect.stringMatching(/request returned (\d+) routes/),