diff --git a/changelog.md b/changelog.md index 60719b916..11b1a1aba 100644 --- a/changelog.md +++ b/changelog.md @@ -82,6 +82,13 @@ For a full record of development, visit our [Github Page](https://github.com/nat ### XXXXday DD/MM/2023 - v3.8.0 {{taskList + +##### Jeddai + +* [X] Add content negotiation to exclude image requests from our API calls + +Fixes issue [#2595](https://github.com/naturalcrit/homebrewery/issues/2595) + ##### G-Ambatte * [x] Update server build scripts to fix Admin page diff --git a/server/app.js b/server/app.js index 5b153d115..22c9d9dac 100644 --- a/server/app.js +++ b/server/app.js @@ -43,8 +43,7 @@ const sanitizeBrew = (brew, accessType)=>{ }; app.use('/', serveCompressedStaticAssets(`build`)); - -//app.use(express.static(`${__dirname}/build`)); +app.use(require('./middleware/content-negotiation.js')); app.use(require('body-parser').json({ limit: '25mb' })); app.use(require('cookie-parser')()); app.use(require('./forcessl.mw.js')); diff --git a/server/middleware/content-negotiation.js b/server/middleware/content-negotiation.js new file mode 100644 index 000000000..201e64a25 --- /dev/null +++ b/server/middleware/content-negotiation.js @@ -0,0 +1,12 @@ +module.exports = (req, res, next)=>{ + const isImageRequest = req.get('Accept')?.split(',') + ?.filter((h)=>!h.includes('q=')) + ?.every((h)=>/image\/.*/.test(h)); + if(isImageRequest) { + return res.status(406).send({ + message : 'Request for image at this URL is not supported' + }); + } + + next(); +}; \ No newline at end of file diff --git a/server/middleware/content-negotiation.spec.js b/server/middleware/content-negotiation.spec.js new file mode 100644 index 000000000..68f22eb1c --- /dev/null +++ b/server/middleware/content-negotiation.spec.js @@ -0,0 +1,41 @@ +const contentNegotiationMiddleware = require('./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(); + }); +}); \ No newline at end of file