diff --git a/.circleci/config.yml b/.circleci/config.yml index d405486b5..00cbdf5bc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -82,6 +82,9 @@ jobs: - run: name: Test - Coverage command: npm run test:coverage + - run: + name: Test - Content Negotiation + command: npm run test:content-negotiation workflows: build_and_test: diff --git a/package.json b/package.json index 31859cce1..16277d5d0 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "test:api-unit:themes": "jest \"server/.*.spec.js\" -t \"theme bundle\" --verbose", "test:api-unit:css": "jest \"server/.*.spec.js\" -t \"Get CSS\" --verbose", "test:api-unit:notifications": "jest \"server/.*.spec.js\" -t \"Notifications\" --verbose", + "test:content-negotiation": "jest \"server/middleware/.*.spec.js\" --verbose", "test:coverage": "jest --coverage --silent --runInBand", "test:dev": "jest --verbose --watch", "test:basic": "jest tests/markdown/basic.test.js --verbose", diff --git a/server/middleware/content-negotiation.js b/server/middleware/content-negotiation.js index ece60e064..9625a5826 100644 --- a/server/middleware/content-negotiation.js +++ b/server/middleware/content-negotiation.js @@ -6,7 +6,7 @@ export default (req, res, next)=>{ const isImageRequest = req.get('Accept')?.split(',') ?.filter((h)=>!h.includes('q=')) ?.every((h)=>/image\/.*/.test(h)); - if(isImageRequest && !isLocalEnvironment && !req.url?.startsWith('/staticImages')) { + if(isImageRequest && !(isLocalEnvironment && req.url?.startsWith('/staticImages'))) { return res.status(406).send({ message : 'Request for image at this URL is not supported' }); diff --git a/server/middleware/content-negotiation.spec.js b/server/middleware/content-negotiation.spec.js new file mode 100644 index 000000000..80b9e515d --- /dev/null +++ b/server/middleware/content-negotiation.spec.js @@ -0,0 +1,41 @@ +import contentNegotiationMiddleware from './content-negotiation.js'; + +describe('content-negotiation-middleware', ()=>{ + let request; + let response; + let next; + + beforeEach(()=>{ + request = { + get : function(key) { + return this[key]; + } + }; + response = { + status : jest.fn(()=>response), + send : jest.fn(()=>{}) + }; + next = jest.fn(); + }); + + it('should return 406 on image request', ()=>{ + contentNegotiationMiddleware({ + Accept : 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8', + ...request + }, response); + + expect(response.status).toHaveBeenLastCalledWith(406); + expect(response.send).toHaveBeenCalledWith({ + message : 'Request for image at this URL is not supported' + }); + }); + + it('should call next on non-image request', ()=>{ + contentNegotiationMiddleware({ + Accept : 'text,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8', + ...request + }, response, next); + + expect(next).toHaveBeenCalled(); + }); +});