const supertest = require('supertest'); jest.mock('request-promise-native'); const Parser = require('rss-parser'); const querystring = require('query-string'); const parser = new Parser(); jest.setTimeout(50000); let server; afterAll(() => { delete process.env.HOTLINK_TEMPLATE; delete process.env.HOTLINK_INCLUDE_PATHS; delete process.env.HOTLINK_EXCLUDE_PATHS; delete process.env.ALLOW_USER_HOTLINK_TEMPLATE; }); afterEach(() => { delete process.env.HOTLINK_TEMPLATE; delete process.env.HOTLINK_INCLUDE_PATHS; delete process.env.HOTLINK_EXCLUDE_PATHS; delete process.env.ALLOW_USER_HOTLINK_TEMPLATE; server.close(); jest.resetModules(); }); const expects = { complicated: { origin: { items: [ ` `, ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, processed: { items: [ ` `, ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, urlencoded: { items: [ ` `, ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, }, multimedia: { origin: { items: [ ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, relayed: { items: [ ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, partlyRelayed: { items: [ ` `, ], desc: ' - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)', }, wrappedInIframe: { items: [ ` `, ], desc: ` - Made with love by RSSHub(https://github.com/DIYgod/RSSHub)`, }, }, }; const testAntiHotlink = async (path, expectObj, query) => { server = require('../../lib/index'); const request = supertest(server); let queryStr; if (query) { queryStr = typeof query === 'string' ? query : querystring.stringify(query); } path = path + (queryStr ? `?${queryStr}` : ''); const response = await request.get(path); const parsed = await parser.parseString(response.text); expect({ items: parsed.items.slice(0, expectObj.items.length).map((i) => i.content), desc: parsed.description, }).toStrictEqual(expectObj); return parsed; }; const expectImgOrigin = (query) => testAntiHotlink('/test/complicated', expects.complicated.origin, query); const expectImgProcessed = (query) => testAntiHotlink('/test/complicated', expects.complicated.processed, query); const expectImgUrlencoded = (query) => testAntiHotlink('/test/complicated', expects.complicated.urlencoded, query); const expectMultimediaOrigin = (query) => testAntiHotlink('/test/multimedia', expects.multimedia.origin, query); const expectMultimediaRelayed = (query) => testAntiHotlink('/test/multimedia', expects.multimedia.relayed, query); const expectMultimediaPartlyRelayed = (query) => testAntiHotlink('/test/multimedia', expects.multimedia.partlyRelayed, query); const expectMultimediaWrappedInIframe = (query) => testAntiHotlink('/test/multimedia', expects.multimedia.wrappedInIframe, query); describe('anti-hotlink', () => { it('template-legacy', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; await expectImgProcessed(); }); it('template-experimental', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.ALLOW_USER_HOTLINK_TEMPLATE = 'true'; await expectImgProcessed(); await expectMultimediaRelayed({ multimedia_hotlink_template: process.env.HOTLINK_TEMPLATE }); }); it('url', async () => { process.env.HOTLINK_TEMPLATE = '${protocol}//${host}${pathname}'; await expectImgOrigin(); await expectMultimediaOrigin({ multimedia_hotlink_template: process.env.HOTLINK_TEMPLATE }); }); it('url-encoded', async () => { process.env.HOTLINK_TEMPLATE = 'https://images.weserv.nl?url=${href_ue}'; await expectImgUrlencoded(); }); it('template-priority-legacy', async () => { process.env.HOTLINK_TEMPLATE = '${protocol}//${host}${pathname}'; await expectImgOrigin(); }); it('template-priority-experimental', async () => { process.env.ALLOW_USER_HOTLINK_TEMPLATE = 'true'; await expectImgOrigin(); await expectImgProcessed({ image_hotlink_template: 'https://i3.wp.com/${host}${pathname}' }); }); it('no-template', async () => { process.env.HOTLINK_TEMPLATE = ''; await expectImgOrigin(); await expectMultimediaOrigin(); }); it('multimedia-template-experimental', async () => { process.env.ALLOW_USER_HOTLINK_TEMPLATE = 'true'; await expectMultimediaOrigin({ multimedia_hotlink_template: '${protocol}//${host}${pathname}' }); await expectMultimediaPartlyRelayed({ multimedia_hotlink_template: 'https://i3.wp.com/${host}${pathname}' }); }); it('multimedia-wrapped-in-iframe-experimental', async () => { await expectMultimediaWrappedInIframe({ wrap_multimedia_in_iframe: '1' }); }); it('include-paths-partial-matched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_INCLUDE_PATHS = '/test'; await expectImgProcessed(); }); it('include-paths-fully-matched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_INCLUDE_PATHS = '/test/complicated'; await expectImgProcessed(); }); it('include-paths-unmatched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_INCLUDE_PATHS = '/t'; await expectImgOrigin(); }); it('exclude-paths-partial-matched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_EXCLUDE_PATHS = '/test'; await expectImgOrigin(); }); it('exclude-paths-fully-matched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_EXCLUDE_PATHS = '/test/complicated'; await expectImgOrigin(); }); it('exclude-paths-unmatched', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_EXCLUDE_PATHS = '/t'; await expectImgProcessed(); }); it('include-exclude-paths-mixed-filtered-out', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_INCLUDE_PATHS = '/test'; process.env.HOTLINK_EXCLUDE_PATHS = '/test/complicated'; await expectImgOrigin(); }); it('include-exclude-paths-mixed-unfiltered-out', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${host}${pathname}'; process.env.HOTLINK_INCLUDE_PATHS = '/test'; process.env.HOTLINK_EXCLUDE_PATHS = '/test/c'; await expectImgProcessed(); }); it('invalid-property', async () => { process.env.HOTLINK_TEMPLATE = 'https://i3.wp.com/${createObjectURL}'; server = require('../../lib/index'); const request = supertest(server); const response = await request.get('/test/complicated'); expect(response.text).toContain('Error: Invalid URL property: createObjectURL'); }); });