From 3ebfa8f189e7a029f4743e6e5ed923b24a8bdd16 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Fri, 7 May 2021 14:57:19 +0200 Subject: [PATCH] Decode req.path before loading object from S3 bucket. Signed-off-by: Eric Peterson --- .../src/stages/publish/awsS3.test.ts | 43 +++++++++++++++++++ .../src/stages/publish/awsS3.ts | 4 +- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index f094457346..fe0fbd556a 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -21,6 +21,8 @@ import { ENTITY_DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; +import express from 'express'; +import request from 'supertest'; import mockFs from 'mock-fs'; import os from 'os'; import path from 'path'; @@ -272,4 +274,45 @@ describe('AwsS3Publish', () => { }); }); }); + + describe('docsRouter', () => { + let app: express.Express; + const entity = createMockEntity(); + const entityRootDir = getEntityRootDir(entity); + + beforeEach(() => { + app = express().use(publisher.docsRouter()); + + mockFs.restore(); + mockFs({ + [entityRootDir]: { + img: { + 'with spaces.png': 'found it', + }, + 'some folder': { + 'also with spaces.js': 'found it too', + }, + }, + }); + }); + + it('should pass expected object path to bucket', async () => { + const { + kind, + metadata: { namespace, name }, + } = entity; + + // Ensures leading slash is trimmed and encoded path is decoded. + const pngResponse = await request(app).get( + `/${namespace}/${kind}/${name}/img/with%20spaces.png`, + ); + expect(Buffer.from(pngResponse.body).toString('utf8')).toEqual( + 'found it', + ); + const jsResponse = await request(app).get( + `/${namespace}/${kind}/${name}/some%20folder/also%20with%20spaces.js`, + ); + expect(jsResponse.text).toEqual('found it too'); + }); + }); }); diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index d628c860fd..e1ffb107cc 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -263,9 +263,9 @@ export class AwsS3Publish implements PublisherBase { */ docsRouter(): express.Handler { return async (req, res) => { - // Trim the leading forward slash + // Decode and trim the leading forward slash // filePath example - /default/Component/documented-component/index.html - const filePath = req.path.replace(/^\//, ''); + const filePath = decodeURI(req.path.replace(/^\//, '')); // Files with different extensions (CSS, HTML) need to be served with different headers const fileExtension = path.extname(filePath);