From d262829cb589032bf2532f336f06120ced61fb46 Mon Sep 17 00:00:00 2001 From: Jonny Adshead Date: Mon, 2 May 2022 11:19:05 -0700 Subject: [PATCH 1/4] chore(workflow): release - checkout tag --- ...se-step-3_automatic_prepare-docker-tags.yml | 4 +++- ...automatic_docker-prod-build-and-publish.yml | 2 ++ ..._automatic_docker-dev-build-and-publish.yml | 2 ++ ...utomatic_publish-one-app-statics-to-npm.yml | 18 ++++++++++-------- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml b/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml index 18e2c3ba..baaafcba 100644 --- a/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml +++ b/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml @@ -15,7 +15,6 @@ jobs: name: Docker Tag Version Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - name: Set env id: set_tag_version run: | @@ -37,6 +36,9 @@ jobs: echo "::error::Incorrect tag provided, please provide a tag with the correct format and try again" exit 1 fi + - uses: actions/checkout@v2 + with: + ref: "${{ steps.set_tag_version.outputs.tagversion}}" - name: Docker tag version id: set_docker_tag_version run: | diff --git a/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml b/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml index 9365ba3c..e11c39c5 100644 --- a/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml +++ b/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml @@ -13,6 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + with: + ref: "v${{ github.event.inputs.docker_tag_version }}" - name: Docker login run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - name: Build production docker image diff --git a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml index cd4a39f6..1eb78808 100644 --- a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml +++ b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml @@ -13,6 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + with: + ref: "v${{ github.event.inputs.docker_tag_version }}" - name: Docker Image Versions id: set_docker_version run: | diff --git a/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml b/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml index aca24006..2fc357a0 100644 --- a/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml +++ b/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml @@ -12,14 +12,6 @@ jobs: name: One App Statics Publish to NPM runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - # Setup .npmrc file to publish to npm - - uses: actions/setup-node@v1 - with: - node-version: '16.x' - registry-url: 'https://registry.npmjs.org' - - name: Docker login - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - name: Tag Version id: set_tag_version run: | @@ -29,6 +21,16 @@ jobs: else echo ::set-output name=tagversion::${{ github.event.inputs.tag_version }} fi + - uses: actions/checkout@v2 + with: + ref: "${{ steps.set_tag_version.outputs.tagversion}}" + # Setup .npmrc file to publish to npm + - uses: actions/setup-node@v1 + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + - name: Docker login + run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - name: Extract and zip production statics run: | docker create --name prod ${{ secrets.DOCKER_USER }}/one-app:${{ steps.set_tag_version.outputs.tagversion}} From 025c9ecad557a7386caf1b60d9cb59b0a6053701 Mon Sep 17 00:00:00 2001 From: Jonny Adshead Date: Mon, 2 May 2022 15:16:08 -0700 Subject: [PATCH 2/4] chore(workflows): release - find tag (#733) --- ...elease-step-3_automatic_prepare-docker-tags.yml | 12 +++++++----- ...p-4_automatic_docker-prod-build-and-publish.yml | 14 +++++++------- ...ep-5_automatic_docker-dev-build-and-publish.yml | 6 +++--- ...-6-automatic_publish-one-app-statics-to-npm.yml | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml b/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml index baaafcba..5eaf761b 100644 --- a/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml +++ b/.github/workflows/release-step-3_automatic_prepare-docker-tags.yml @@ -21,7 +21,7 @@ jobs: #Checks for when a valid tag is manually pushed if [[ $GITHUB_REF != "" && "${{ github.event.client_payload.tagversion }}" == "" ]]; then - echo ::set-output name=tagversion::$(egrep -o '(v[0-9]+\.[0-9]+\.[0-9]+)(-\S*)?' <<< $GITHUB_REF) + echo ::set-output name=tagversion::$(egrep -o '^v([0-9]+\.[0-9]+\.[0-9]+)(-\S*)?' <<< $GITHUB_REF) else echo ::set-output name=tagversion::${{ github.event.client_payload.tagversion }} fi @@ -36,14 +36,16 @@ jobs: echo "::error::Incorrect tag provided, please provide a tag with the correct format and try again" exit 1 fi - - uses: actions/checkout@v2 - with: - ref: "${{ steps.set_tag_version.outputs.tagversion}}" - name: Docker tag version id: set_docker_tag_version run: | - tagversion=${{ steps.set_tag_version.outputs.tagversion}} + # trimmed off 'v' from tagversion + tagversion=${{ steps.set_tag_version.outputs.tagversion }} echo ::set-output name=dockertag::$(sed 's/^v*//' <<< "$tagversion") + # ensure tag is available + - uses: actions/checkout@v2 + with: + ref: "v${{ steps.set_docker_tag_version.outputs.dockertag }}" - name: Trigger Production Image Publishing uses: octokit/request-action@v2.x id: dispatch_release-step-4_automatic_docker-prod-build-and-publish diff --git a/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml b/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml index e11c39c5..9c6775d0 100644 --- a/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml +++ b/.github/workflows/release-step-4_automatic_docker-prod-build-and-publish.yml @@ -12,13 +12,6 @@ jobs: name: One App Production Image Build and Push runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - with: - ref: "v${{ github.event.inputs.docker_tag_version }}" - - name: Docker login - run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - - name: Build production docker image - run: docker build -t prod . - name: Extract sem versions id: get_sem_version run: | @@ -43,6 +36,13 @@ jobs: echo ::set-output name=major_version::${MAJOR} echo ::set-output name=minor_version::${MINOR} fi + - uses: actions/checkout@v2 + with: + ref: "v${{ steps.set_docker_version.outputs.docker_version }}" + - name: Docker login + run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin + - name: Build production docker image + run: docker build -t prod . - name: Tag Docker Images run: | docker tag prod ${{ secrets.DOCKER_USER }}/one-app:${{ steps.set_docker_version.outputs.major_version}} diff --git a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml index 1eb78808..961932bd 100644 --- a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml +++ b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml @@ -12,9 +12,6 @@ jobs: name: One App Development Image Build and Push runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - with: - ref: "v${{ github.event.inputs.docker_tag_version }}" - name: Docker Image Versions id: set_docker_version run: | @@ -34,6 +31,9 @@ jobs: - name: Print docker version run: | echo "tag: ${{ github.event.inputs.docker_tag_version }}" + - uses: actions/checkout@v2 + with: + ref: "v${{ github.event.inputs.docker_tag_version }}" - name: Docker login run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - name: Build development docker image diff --git a/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml b/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml index 2fc357a0..3471941c 100644 --- a/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml +++ b/.github/workflows/release-step-6-automatic_publish-one-app-statics-to-npm.yml @@ -23,7 +23,7 @@ jobs: fi - uses: actions/checkout@v2 with: - ref: "${{ steps.set_tag_version.outputs.tagversion}}" + ref: "v${{ steps.set_tag_version.outputs.tagversion}}" # Setup .npmrc file to publish to npm - uses: actions/setup-node@v1 with: From a1abb4986b922162935847fb0e042576f1c72b53 Mon Sep 17 00:00:00 2001 From: Jamie King Date: Mon, 2 May 2022 16:03:56 -0700 Subject: [PATCH 3/4] feat(ssrServer): make max POST request payload size configurable (#721) Co-authored-by: Matthew Mallimo --- .../env/__snapshots__/runTime.spec.js.snap | 6 -- __tests__/server/config/env/runTime.spec.js | 96 ++++++++++++++++--- __tests__/server/ssrServer.spec.js | 9 +- docs/api/server/Environment-Variables.md | 33 ++++++- package-lock.json | 1 + package.json | 3 +- src/server/config/env/runTime.js | 30 +++++- src/server/ssrServer.js | 6 +- 8 files changed, 155 insertions(+), 29 deletions(-) diff --git a/__tests__/server/config/env/__snapshots__/runTime.spec.js.snap b/__tests__/server/config/env/__snapshots__/runTime.spec.js.snap index 4b215c9c..4efa1f02 100644 --- a/__tests__/server/config/env/__snapshots__/runTime.spec.js.snap +++ b/__tests__/server/config/env/__snapshots__/runTime.spec.js.snap @@ -1,14 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`runTime HTTP_ONE_APP_DEV_CDN_PORT normalizes numeric input 1`] = `"env var HTTP_ONE_APP_DEV_CDN_PORT needs to be a valid integer, given \\"0002345a\\""`; - -exports[`runTime HTTP_ONE_APP_DEV_PROXY_SERVER_PORT normalizes numeric input: env var HTTP_ONE_APP_DEV_PROXY_SERVER_PORT needs to be a valid integer, given "r00t" 1`] = `"env var HTTP_ONE_APP_DEV_PROXY_SERVER_PORT needs to be a valid integer, given \\"r00t\\""`; - exports[`runTime NODE_ENV only allows for values to be set to either development or production 1`] = ` Array [ "development", "production", ] `; - -exports[`runTime ONE_CLIENT_ROOT_MODULE_NAME validates that environment value is defined 1`] = `"The \`ONE_CLIENT_ROOT_MODULE_NAME\` environment variable must be defined."`; diff --git a/__tests__/server/config/env/runTime.spec.js b/__tests__/server/config/env/runTime.spec.js index 3eeaf12d..4adadd68 100644 --- a/__tests__/server/config/env/runTime.spec.js +++ b/__tests__/server/config/env/runTime.spec.js @@ -47,8 +47,11 @@ describe('runTime', () => { 'ONE_CLIENT_CDN_URL', 'ONE_CLIENT_LOCALE_FILENAME', 'ONE_CLIENT_ROOT_MODULE_NAME', - ] - .forEach((name) => { origEnvVarVals[name] = process.env[name]; }); + 'ONE_ENABLE_POST_TO_MODULE_ROUTES', + 'ONE_MAX_POST_REQUEST_PAYLOAD', + ].forEach((name) => { + origEnvVarVals[name] = process.env[name]; + }); function getEnvVarConfig(envVarName) { const runTime = require('../../../../src/server/config/env/runTime').default; @@ -70,6 +73,7 @@ describe('runTime', () => { resetEnvVar('NODE_ENV'); resetEnvVar('ONE_DANGEROUSLY_DISABLE_CSP', 'false'); resetEnvVar('HTTP_ONE_APP_DEV_CDN_PORT'); + resetEnvVar('ONE_ENABLE_POST_TO_MODULE_ROUTES'); jest.resetModules(); jest.resetAllMocks(); }); @@ -78,9 +82,7 @@ describe('runTime', () => { // eslint-disable-next-line no-console console.info = origConsoleInfo; console.warn = origConsoleWarn; - Object - .keys(origEnvVarVals) - .forEach((name) => resetEnvVar(name, origEnvVarVals[name])); + Object.keys(origEnvVarVals).forEach((name) => resetEnvVar(name, origEnvVarVals[name])); jest.resetAllMocks(); }); @@ -131,13 +133,17 @@ describe('runTime', () => { const disableCspEnv = getEnvVarConfig('ONE_DANGEROUSLY_DISABLE_CSP'); it('throws error if ONE_DANGEROUSLY_DISABLE_CSP is set to true and NODE_ENV is not development', () => { - expect(() => disableCspEnv.validate('true')).toThrowError('If you are trying to bypass CSP requirement, NODE_ENV must also be set to development.'); + expect(() => disableCspEnv.validate('true')).toThrowError( + 'If you are trying to bypass CSP requirement, NODE_ENV must also be set to development.' + ); }); it('warns console if both ONE_DANGEROUSLY_DISABLE_CSP and NODE_ENV are set properly', () => { process.env.NODE_ENV = 'development'; disableCspEnv.validate('true'); - expect(console.warn).toHaveBeenCalledWith('ONE_DANGEROUSLY_DISABLE_CSP is true and NODE_ENV is set to development. Content-Security-Policy header will not be set.'); + expect(console.warn).toHaveBeenCalledWith( + 'ONE_DANGEROUSLY_DISABLE_CSP is true and NODE_ENV is set to development. Content-Security-Policy header will not be set.' + ); }); it('does not warn or throw if ONE_DANGEROUSLY_DISABLE_CSP is set to false', () => { @@ -190,7 +196,9 @@ describe('runTime', () => { 'env var HTTP_ONE_APP_DEV_CDN_PORT needs to be a valid integer, given "r00t"' ); expect(devCdnPort.normalize('0002345')).toEqual(2345); - expect(() => devCdnPort.normalize('0002345a')).toThrowErrorMatchingSnapshot(); + expect(() => devCdnPort.normalize('0002345a')).toThrowErrorMatchingInlineSnapshot( + '"env var HTTP_ONE_APP_DEV_CDN_PORT needs to be a valid integer, given \\"0002345a\\""' + ); }); it('does not normalize if no value is given', () => { @@ -215,8 +223,8 @@ describe('runTime', () => { it('normalizes numeric input', () => { expect(devProxyPort.normalize('1337')).toEqual(1337); - expect(() => devProxyPort.normalize('r00t')).toThrowErrorMatchingSnapshot( - 'env var HTTP_ONE_APP_DEV_PROXY_SERVER_PORT needs to be a valid integer, given "r00t"' + expect(() => devProxyPort.normalize('r00t')).toThrowErrorMatchingInlineSnapshot( + '"env var HTTP_ONE_APP_DEV_PROXY_SERVER_PORT needs to be a valid integer, given \\"r00t\\""' ); expect(devProxyPort.normalize('0002345')).toEqual(2345); expect(() => devProxyPort.normalize('0002345a')).toThrow(); @@ -263,7 +271,9 @@ describe('runTime', () => { process.env.NODE_ENV = 'development'; process.env.HTTP_ONE_APP_DEV_CDN_PORT = 3001; expect(holocronModuleMapPath.defaultValue()).toBeDefined(); - expect(holocronModuleMapPath.defaultValue()).toBe('http://localhost:3001/static/module-map.json'); + expect(holocronModuleMapPath.defaultValue()).toBe( + 'http://localhost:3001/static/module-map.json' + ); }); it('has no default value for production', () => { @@ -293,13 +303,18 @@ describe('runTime', () => { }); describe('HOLOCRON_SERVER_MAX_SIM_MODULES_FETCH', () => { - const holocronServerMaxSimModulesFetch = getEnvVarConfig('HOLOCRON_SERVER_MAX_SIM_MODULES_FETCH'); + const holocronServerMaxSimModulesFetch = getEnvVarConfig( + 'HOLOCRON_SERVER_MAX_SIM_MODULES_FETCH' + ); it('does not have a default value', () => { expect(holocronServerMaxSimModulesFetch.defaultValue).toBe(undefined); }); - it('validates the value as a positive integer', positiveInteger(holocronServerMaxSimModulesFetch)); + it( + 'validates the value as a positive integer', + positiveInteger(holocronServerMaxSimModulesFetch) + ); }); describe('ONE_CLIENT_REPORTING_URL', () => { @@ -390,7 +405,9 @@ describe('runTime', () => { const clientRootModuleName = getEnvVarConfig('ONE_CLIENT_ROOT_MODULE_NAME'); it('validates that environment value is defined', () => { - expect(() => clientRootModuleName.validate()).toThrowErrorMatchingSnapshot(); + expect(() => clientRootModuleName.validate()).toThrowErrorMatchingInlineSnapshot( + '"The `ONE_CLIENT_ROOT_MODULE_NAME` environment variable must be defined."' + ); expect(() => clientRootModuleName.validate('frank-lloyd-root')).not.toThrow(); }); @@ -432,4 +449,55 @@ describe('runTime', () => { expect(oneServiceWorkerFeatureFlag.normalize('true')).toEqual(true); }); }); + + describe('ONE_ENABLE_POST_TO_MODULE_ROUTES', () => { + const enablePostToModuleRoutes = getEnvVarConfig('ONE_ENABLE_POST_TO_MODULE_ROUTES'); + + it('should have a default value of "false"', () => { + expect(enablePostToModuleRoutes.defaultValue).toBe('false'); + }); + + it('should normalize the value to lower case', () => { + expect(enablePostToModuleRoutes.normalize('Value')).toBe('value'); + expect(enablePostToModuleRoutes.normalize('VALUE')).toBe('value'); + }); + + it('should pass validation when value is "true" or "false"', () => { + expect(() => enablePostToModuleRoutes.validate('true')).not.toThrow(); + expect(() => enablePostToModuleRoutes.validate('false')).not.toThrow(); + }); + + it('should fail validation when value is not "true" or "false"', () => { + expect(() => enablePostToModuleRoutes.validate('bad value') + ).toThrowErrorMatchingInlineSnapshot( + '"Expected \\"bad value\\" to be \\"true\\" or \\"false\\""' + ); + }); + }); + + describe('ONE_MAX_POST_REQUEST_PAYLOAD', () => { + const postRequestMaxPayload = getEnvVarConfig('ONE_MAX_POST_REQUEST_PAYLOAD'); + + it('should have a default value of "15kb"', () => { + expect(postRequestMaxPayload.defaultValue).toBe('15kb'); + }); + + it('should fail validation when input is not parseable by bytes util', () => { + process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES = true; + expect(() => postRequestMaxPayload.validate('bad value')).toThrowErrorMatchingInlineSnapshot( + '"Expected \\"bad value\\" to be parseable by bytes utility https://www.npmjs.com/package/bytes"' + ); + }); + + it('should pass validation when input is parseable by bytes util', () => { + process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES = true; + expect(() => postRequestMaxPayload.validate('20kb')).not.toThrow(); + }); + + it('should fail validation when POSTing is not enabled', () => { + expect(() => postRequestMaxPayload.validate('20kb')).toThrowErrorMatchingInlineSnapshot( + '"ONE_ENABLE_POST_TO_MODULE_ROUTES must be \\"true\\" to configure max POST payload."' + ); + }); + }); }); diff --git a/__tests__/server/ssrServer.spec.js b/__tests__/server/ssrServer.spec.js index 1adff503..32f80c17 100644 --- a/__tests__/server/ssrServer.spec.js +++ b/__tests__/server/ssrServer.spec.js @@ -65,6 +65,7 @@ describe('ssrServer', () => { jest.clearAllMocks(); process.env.NODE_ENV = 'development'; delete process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES; + delete process.env.ONE_MAX_POST_REQUEST_PAYLOAD; }); describe('middleware order', () => { @@ -288,7 +289,7 @@ describe('ssrServer', () => { describe('enablePostToModuleRoutes', () => { beforeEach(() => { - process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES = 'yes'; + process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES = 'true'; }); it('should check the state for a status code for all post calls', async () => { @@ -331,10 +332,11 @@ describe('ssrServer', () => { }); it('should configure json parsing with a maximum limit for render post calls', async () => { + process.env.ONE_MAX_POST_REQUEST_PAYLOAD = '100kb'; await request(loadServer()) .post('/route'); expect(json).toBeCalled(); - expect(json.mock.calls[2][0]).toHaveProperty('limit', '15kb'); + expect(json.mock.calls[2][0]).toHaveProperty('limit', '100kb'); }); it('should configure urlencoded parsing with a maximum limit for render post pre-flight options calls', async () => { await request(loadServer()) @@ -344,10 +346,11 @@ describe('ssrServer', () => { }); it('should configure json urlencoded with a maximum limit for render post calls', async () => { + process.env.ONE_MAX_POST_REQUEST_PAYLOAD = '25kb'; await request(loadServer()) .post('/route'); expect(urlencoded).toBeCalled(); - expect(json.mock.calls[2][0]).toHaveProperty('limit', '15kb'); + expect(json.mock.calls[2][0]).toHaveProperty('limit', '25kb'); }); describe('cors for render post calls', () => { diff --git a/docs/api/server/Environment-Variables.md b/docs/api/server/Environment-Variables.md index f188121b..d3286e9f 100644 --- a/docs/api/server/Environment-Variables.md +++ b/docs/api/server/Environment-Variables.md @@ -40,6 +40,7 @@ One App can be configured via Environment Variables: * [`HOLOCRON_SERVER_MAX_MODULES_RETRY`](#holocron_server_max_modules_retry) * [`HOLOCRON_SERVER_MAX_SIM_MODULES_FETCH`](#holocron_server_max_sim_modules_fetch) * [`ONE_ENABLE_POST_TO_MODULE_ROUTES`](#one_enable_post_to_module_routes) + * [`ONE_MAX_POST_REQUEST_PAYLOAD`](#one_max_post_request_payload) * [`ONE_MAP_POLLING_MAX`](#one_map_polling_max) * [`ONE_MAP_POLLING_MIN`](#one_map_polling_min) * [`ONE_REFERRER_POLICY_OVERRIDE`](#one_referrer_policy_override) @@ -71,6 +72,7 @@ One App can be configured via Environment Variables: * [`ONE_ENABLE_POST_TO_MODULE_ROUTES`](#one_enable_post_to_module_routes) * [`ONE_MAP_POLLING_MAX`](#one_map_polling_max) * [`ONE_MAP_POLLING_MIN`](#one_map_polling_min) + * [`ONE_MAX_POST_REQUEST_PAYLOAD`](#one_max_post_request_payload) * [`ONE_REFERRER_POLICY_OVERRIDE`](#one_referrer_policy_override) * [`ONE_SERVICE_WORKER`](#one_service_worker) @@ -589,18 +591,46 @@ ONE_DANGEROUSLY_DISABLE_CSP=false * ✅ Production * ✅ Development -Set if One App should respond to POST requests. +Set to true if One App should respond to POST requests. **Shape** ```bash ONE_ENABLE_POST_TO_MODULE_ROUTES=Boolean ``` +**Example** +```bash +ONE_ENABLE_POST_TO_MODULE_ROUTES=true +``` + **Default Value** ```bash ONE_ENABLE_POST_TO_MODULE_ROUTES=false ``` +## `ONE_MAX_POST_REQUEST_PAYLOAD` + +**Runs In** +* ✅ Production +* ✅ Development + +Maximum payload allowed in POST requests. `ONE_ENABLE_POST_TO_MODULE_ROUTES` must be true to configure this. + +**Shape** +```bash +ONE_MAX_POST_REQUEST_PAYLOAD=String +``` + +**Example** +```bash +ONE_MAX_POST_REQUEST_PAYLOAD=100kb +``` + +**Default Value** +```bash +ONE_MAX_POST_REQUEST_PAYLOAD=15kb +``` + ## `ONE_MAP_POLLING_MAX` **Runs In** @@ -684,6 +714,7 @@ ONE_SERVICE_WORKER=true ONE_SERVICE_WORKER=false ``` + **📘 More Information** * Useful NodeJS Env Variables: [Node CLI Docs](https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file) * [Development Tools Documentation](./Development-Tools.md) diff --git a/package-lock.json b/package-lock.json index 83ccbccb..82f8aae0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@americanexpress/vitruvius": "^2.0.2", "abort-controller": "^3.0.0", "body-parser": "^1.19.0", + "bytes": "^3.1.2", "chalk": "^4.1.2", "compression": "^1.7.4", "cookie-parser": "^1.4.5", diff --git a/package.json b/package.json index 0dfa6188..936e6a4c 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "contributors": [ "Andres Escobar (https://github.com/anescobar1991)", "James Singleton (https://github.com/JamesSingleton)", - "Jimmy King (https://github.com/10xLaCroixDrinker)", + "Jamie King (https://github.com/10xLaCroixDrinker)", "Jonathan Adshead (https://github.com/JAdshead)", "Michael Tobia (https://github.com/Francois-Esquire)", "Michael Tomcal (https://github.com/mtomcal)", @@ -87,6 +87,7 @@ "@americanexpress/vitruvius": "^2.0.2", "abort-controller": "^3.0.0", "body-parser": "^1.19.0", + "bytes": "^3.1.2", "chalk": "^4.1.2", "compression": "^1.7.4", "cookie-parser": "^1.4.5", diff --git a/src/server/config/env/runTime.js b/src/server/config/env/runTime.js index cc96586f..030b33b9 100644 --- a/src/server/config/env/runTime.js +++ b/src/server/config/env/runTime.js @@ -19,6 +19,7 @@ const { preprocessEnvVar } = require('@americanexpress/env-config-utils'); const isFetchableUrlInNode = require('@americanexpress/env-config-utils/isFetchableUrlInNode'); const isFetchableUrlInBrowser = require('@americanexpress/env-config-utils/isFetchableUrlInBrowser'); const { argv } = require('yargs'); +const bytes = require('bytes'); const isPositiveIntegerIfDefined = (input) => { if (input === undefined) { @@ -197,7 +198,7 @@ const runTime = [ ]; if (!approvedPolicies.includes(value)) { - throw new Error(`${value} in not an approved policy. Please use: ${approvedPolicies.join(',')}.`); + throw new Error(`"${value}" is not an approved policy. Please use: ${approvedPolicies.join(',')}.`); } }, }, @@ -208,6 +209,33 @@ const runTime = [ normalize: (value) => value === 'true', defaultValue: () => false, }, + // Enable POSTing to module routes + { + name: 'ONE_ENABLE_POST_TO_MODULE_ROUTES', + defaultValue: 'false', + normalize: (input) => input.toLowerCase(), + validate: (input) => { + if (input !== 'true' && input !== 'false') { + throw new Error(`Expected "${input}" to be "true" or "false"`); + } + }, + }, + // Customize max payload for POST requests + { + name: 'ONE_MAX_POST_REQUEST_PAYLOAD', + defaultValue: '15kb', + validate: (input) => { + if (process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES !== 'true') { + throw new Error('ONE_ENABLE_POST_TO_MODULE_ROUTES must be "true" to configure max POST payload.'); + } + + const parsed = bytes.parse(input); + + if (parsed === null) { + throw new Error(`Expected "${input}" to be parseable by bytes utility https://www.npmjs.com/package/bytes`); + } + }, + }, ]; runTime.forEach(preprocessEnvVar); export { ip }; diff --git a/src/server/ssrServer.js b/src/server/ssrServer.js index f9df9eb3..639b7154 100644 --- a/src/server/ssrServer.js +++ b/src/server/ssrServer.js @@ -103,8 +103,8 @@ export function createApp({ enablePostToModuleRoutes = false } = {}) { app.post( '*', addSecurityHeaders, - json({ limit: '15kb' }), - urlencoded({ limit: '15kb' }), + json({ limit: process.env.ONE_MAX_POST_REQUEST_PAYLOAD }), + urlencoded({ limit: process.env.ONE_MAX_POST_REQUEST_PAYLOAD }), addFrameOptionsHeader, createRequestStore(oneApp, { useBodyForBuildingTheInitialState: true }), createRequestHtmlFragment(oneApp), @@ -123,5 +123,5 @@ export function createApp({ enablePostToModuleRoutes = false } = {}) { } export default createApp({ - enablePostToModuleRoutes: !!process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES, + enablePostToModuleRoutes: process.env.ONE_ENABLE_POST_TO_MODULE_ROUTES === 'true', }); From 7d2cc3051aa7aa6e7c645d17f17e6d4d811017fc Mon Sep 17 00:00:00 2001 From: Jonny Adshead Date: Tue, 3 May 2022 07:30:20 -0700 Subject: [PATCH 4/4] chore(workflows): docker-dev-build fix tag (#734) --- .../release-step-5_automatic_docker-dev-build-and-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml index 961932bd..f7ac0be3 100644 --- a/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml +++ b/.github/workflows/release-step-5_automatic_docker-dev-build-and-publish.yml @@ -30,10 +30,10 @@ jobs: fi - name: Print docker version run: | - echo "tag: ${{ github.event.inputs.docker_tag_version }}" + echo "tag: ${{ steps.set_docker_version.outputs.docker_version }}" - uses: actions/checkout@v2 with: - ref: "v${{ github.event.inputs.docker_tag_version }}" + ref: "v${{ steps.set_docker_version.outputs.docker_version }}" - name: Docker login run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login --username ${{ secrets.DOCKER_USER }} --password-stdin - name: Build development docker image