From a3cbe37aa4ea1711bb7b2cbfc09b0470e842d031 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 1 Jul 2021 10:02:05 +0200 Subject: [PATCH] backstage-common(GithubUrlReader): Return etag from readUrl, add tests Signed-off-by: Johan Haals --- .../src/reading/GithubUrlReader.test.ts | 107 ++++++++++++++++++ .../src/reading/GithubUrlReader.ts | 8 +- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/GithubUrlReader.test.ts b/packages/backend-common/src/reading/GithubUrlReader.test.ts index 0b3288e59c..c8002cd3ce 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.test.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.test.ts @@ -141,6 +141,113 @@ describe('GithubUrlReader', () => { }); }); + /* + * readUrl + */ + describe('readUrl', () => { + it('should use the headers from the credentials provider to the fetch request when doing readUrl', async () => { + expect.assertions(2); + + const mockHeaders = { + Authorization: 'bearer blah', + otherheader: 'something', + }; + + (mockCredentialsProvider.getCredentials as jest.Mock).mockResolvedValue({ + headers: mockHeaders, + }); + + worker.use( + rest.get( + 'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/', + (req, res, ctx) => { + expect(req.headers.get('authorization')).toBe( + mockHeaders.Authorization, + ); + expect(req.headers.get('otherheader')).toBe( + mockHeaders.otherheader, + ); + return res( + ctx.status(200), + ctx.set('Content-Type', 'application/x-gzip'), + ctx.body('foo'), + ); + }, + ), + ); + + await gheProcessor.readUrl( + 'https://github.com/backstage/mock/tree/blob/main', + ); + }); + + it('should throw NotModified if GitHub responds with 304', async () => { + expect.assertions(4); + + const mockHeaders = { + Authorization: 'bearer blah', + otherheader: 'something', + }; + + (mockCredentialsProvider.getCredentials as jest.Mock).mockResolvedValue({ + headers: mockHeaders, + }); + + worker.use( + rest.get( + 'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/', + (req, res, ctx) => { + expect(req.headers.get('authorization')).toBe( + mockHeaders.Authorization, + ); + expect(req.headers.get('otherheader')).toBe( + mockHeaders.otherheader, + ); + expect(req.headers.get('if-none-match')).toBe('foo'); + return res( + ctx.status(304), + ctx.set('Content-Type', 'application/x-gzip'), + ctx.body('foo'), + ); + }, + ), + ); + + await expect( + gheProcessor.readUrl( + 'https://github.com/backstage/mock/tree/blob/main', + { etag: 'foo' }, + ), + ).rejects.toThrow(NotModifiedError); + }); + + it('should return etag from the response', async () => { + (mockCredentialsProvider.getCredentials as jest.Mock).mockResolvedValue({ + headers: { + Authorization: 'bearer blah', + }, + }); + + worker.use( + rest.get( + 'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/', + (_req, res, ctx) => { + return res( + ctx.status(200), + ctx.set('Etag', 'foo'), + ctx.body('bar'), + ); + }, + ), + ); + + const response = await gheProcessor.readUrl( + 'https://github.com/backstage/mock/tree/blob/main', + ); + expect(response.etag).toBe('foo'); + }); + }); + /* * readTree */ diff --git a/packages/backend-common/src/reading/GithubUrlReader.ts b/packages/backend-common/src/reading/GithubUrlReader.ts index 7d12634365..946d863154 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.ts @@ -109,7 +109,13 @@ export class GithubUrlReader implements UrlReader { } if (response.ok) { - return { buffer: async () => Buffer.from(await response.text()) }; + const etag = response.headers.get('ETag') + ? response.headers.get('ETag')! + : undefined; + return { + buffer: async () => Buffer.from(await response.text()), + etag, + }; } const message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`;