From 1c039abf4f1abbef07941abbe2beacb4877d1212 Mon Sep 17 00:00:00 2001 From: HKWinterhalter Date: Mon, 17 Mar 2025 14:59:17 -0700 Subject: [PATCH 1/5] chore: remove all assignees from blunderbuss.yml (#678) --- .github/blunderbuss.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/blunderbuss.yml b/.github/blunderbuss.yml index 30123090..8b137891 100644 --- a/.github/blunderbuss.yml +++ b/.github/blunderbuss.yml @@ -1,11 +1 @@ -assign_prs: - - HKwinterhalter - - jihuin - - chujchen - - liuyunnnn -assign_issues: - - HKwinterhalter - - jihuin - - chujchen - - liuyunnnn From 70f68e9d0b4fa1db6345ab012ddfec0fd983f762 Mon Sep 17 00:00:00 2001 From: Matthew Robertson Date: Thu, 27 Mar 2025 09:12:30 -0700 Subject: [PATCH 2/5] introduce a new option for configuring ignored routes (#679) --- README.md | 1 + src/options.ts | 13 ++++++++++++- src/server.ts | 15 ++++++++++++--- src/testing.ts | 1 + test/integration/legacy_event.ts | 1 + test/options.ts | 8 ++++++++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1039d7f8..88144492 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ ignored. | `--signature-type` | `FUNCTION_SIGNATURE_TYPE` | The signature used when writing your function. Controls unmarshalling rules and determines which arguments are used to invoke your function. Default: `http`; accepted values: `http` or `event` or `cloudevent` | | `--source` | `FUNCTION_SOURCE` | The path to the directory of your function. Default: `cwd` (the current working directory) | | `--log-execution-id`| `LOG_EXECUTION_ID` | Enables execution IDs in logs, either `true` or `false`. When not specified, default to disable. Requires Node.js 13.0.0 or later. | +| `--ignored-routes`| `IGNORED_ROUTES` | A route expression for requests that should not be routed the function. An empty 404 response will be returned. This is set to `/favicon.ico|/robots.txt` by default for `http` functions. | You can set command-line flags in your `package.json` via the `start` script. For example: diff --git a/src/options.ts b/src/options.ts index 96de71c8..a0e9c89f 100644 --- a/src/options.ts +++ b/src/options.ts @@ -56,6 +56,10 @@ export interface FrameworkOptions { * The request timeout. */ timeoutMilliseconds: number; + /** + * Routes that should return a 404 without invoking the function. + */ + ignoredRoutes: string | null; } /** @@ -86,7 +90,7 @@ class ConfigurableOption { parse(cliArgs: minimist.ParsedArgs, envVars: NodeJS.ProcessEnv): T { return this.validator( - cliArgs[this.cliOption] || envVars[this.envVar] || this.defaultValue + cliArgs[this.cliOption] ?? envVars[this.envVar] ?? this.defaultValue ); } } @@ -130,6 +134,11 @@ const TimeoutOption = new ConfigurableOption( return x * 1000; } ); +const IgnoredRoutesOption = new ConfigurableOption( + 'ignored-routes', + 'IGNORED_ROUTES', + null // null by default so we can detect if it is explicitly set to "" +); export const requiredNodeJsVersionForLogExecutionID = '13.0.0'; const ExecutionIdOption = new ConfigurableOption( @@ -181,6 +190,7 @@ export const parseOptions = ( SignatureOption.cliOption, SourceLocationOption.cliOption, TimeoutOption.cliOption, + IgnoredRoutesOption.cliOption, ], }); return { @@ -191,5 +201,6 @@ export const parseOptions = ( timeoutMilliseconds: TimeoutOption.parse(argv, envVars), printHelp: cliArgs[2] === '-h' || cliArgs[2] === '--help', enableExecutionId: ExecutionIdOption.parse(argv, envVars), + ignoredRoutes: IgnoredRoutesOption.parse(argv, envVars), }; }; diff --git a/src/server.ts b/src/server.ts index bc348141..fbf565c6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -134,14 +134,23 @@ export function getServer( if (options.signatureType === 'cloudevent') { app.use(backgroundEventToCloudEventMiddleware); } - - if (options.signatureType === 'http') { + if (options.ignoredRoutes !== null) { + // Ignored routes is a configuration option that allows requests to specific paths to be prevented + // from invoking the user's function. + app.use(options.ignoredRoutes, (req, res) => { + res.status(404).send(null); + }); + } else if (options.signatureType === 'http') { + // We configure some default ignored routes, only for HTTP functions. app.use('/favicon.ico|/robots.txt', (req, res) => { // Neither crawlers nor browsers attempting to pull the icon find the body - // contents particularly useful, so we send nothing in the response body. + // contents particularly useful, so we filter these requests out from invoking + // the user's function by default. res.status(404).send(null); }); + } + if (options.signatureType === 'http') { app.use('/*', (req, res, next) => { onFinished(res, (err, res) => { res.locals.functionExecutionFinished = true; diff --git a/src/testing.ts b/src/testing.ts index 9cb62c9d..2fda93c2 100644 --- a/src/testing.ts +++ b/src/testing.ts @@ -56,5 +56,6 @@ export const getTestServer = (functionName: string): Server => { target: '', sourceLocation: '', printHelp: false, + ignoredRoutes: null, }); }; diff --git a/test/integration/legacy_event.ts b/test/integration/legacy_event.ts index a25250e6..231d0f62 100644 --- a/test/integration/legacy_event.ts +++ b/test/integration/legacy_event.ts @@ -40,6 +40,7 @@ const testOptions = { target: '', sourceLocation: '', printHelp: false, + ignoredRoutes: null, }; describe('Event Function', () => { diff --git a/test/options.ts b/test/options.ts index bf1619d0..b6279485 100644 --- a/test/options.ts +++ b/test/options.ts @@ -60,6 +60,7 @@ describe('parseOptions', () => { printHelp: false, enableExecutionId: false, timeoutMilliseconds: 0, + ignoredRoutes: null, }, }, { @@ -75,6 +76,7 @@ describe('parseOptions', () => { '--source=/source', '--timeout', '6', + '--ignored-routes=banana', ], envVars: {}, expectedOptions: { @@ -85,6 +87,7 @@ describe('parseOptions', () => { printHelp: false, enableExecutionId: false, timeoutMilliseconds: 6000, + ignoredRoutes: 'banana', }, }, { @@ -96,6 +99,7 @@ describe('parseOptions', () => { FUNCTION_SIGNATURE_TYPE: 'cloudevent', FUNCTION_SOURCE: '/source', CLOUD_RUN_TIMEOUT_SECONDS: '2', + IGNORED_ROUTES: '', }, expectedOptions: { port: '1234', @@ -105,6 +109,7 @@ describe('parseOptions', () => { printHelp: false, enableExecutionId: false, timeoutMilliseconds: 2000, + ignoredRoutes: '', }, }, { @@ -119,6 +124,7 @@ describe('parseOptions', () => { 'cloudevent', '--source=/source', '--timeout=3', + '--ignored-routes=avocado', ], envVars: { PORT: '4567', @@ -126,6 +132,7 @@ describe('parseOptions', () => { FUNCTION_SIGNATURE_TYPE: 'event', FUNCTION_SOURCE: '/somewhere/else', CLOUD_RUN_TIMEOUT_SECONDS: '5', + IGNORED_ROUTES: 'banana', }, expectedOptions: { port: '1234', @@ -135,6 +142,7 @@ describe('parseOptions', () => { printHelp: false, enableExecutionId: false, timeoutMilliseconds: 3000, + ignoredRoutes: 'avocado', }, }, ]; From 053a4ca94b6357507a124e6356d09649f5a7a7b3 Mon Sep 17 00:00:00 2001 From: Matthew Robertson Date: Thu, 27 Mar 2025 10:10:37 -0700 Subject: [PATCH 3/5] chore: nodejs versions in github workflows (#680) --- .../workflows/buildpack-integration-test.yml | 51 +++++-------------- .github/workflows/conformance.yml | 2 +- .github/workflows/docs.yml | 2 +- .github/workflows/publish.yml | 4 +- .github/workflows/unit.yml | 2 +- 5 files changed, 17 insertions(+), 44 deletions(-) diff --git a/.github/workflows/buildpack-integration-test.yml b/.github/workflows/buildpack-integration-test.yml index 663689a7..d90a046f 100644 --- a/.github/workflows/buildpack-integration-test.yml +++ b/.github/workflows/buildpack-integration-test.yml @@ -14,37 +14,7 @@ on: permissions: read-all jobs: - nodejs10: - uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main - with: - http-builder-source: 'test/conformance' - http-builder-target: 'writeHttpDeclarative' - cloudevent-builder-source: 'test/conformance' - cloudevent-builder-target: 'writeCloudEventDeclarative' - prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs10' - builder-runtime-version: '10' - nodejs12: - uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main - with: - http-builder-source: 'test/conformance' - http-builder-target: 'writeHttpDeclarative' - cloudevent-builder-source: 'test/conformance' - cloudevent-builder-target: 'writeCloudEventDeclarative' - prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs12' - builder-runtime-version: '12' - nodejs14: - uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main - with: - http-builder-source: 'test/conformance' - http-builder-target: 'writeHttpDeclarative' - cloudevent-builder-source: 'test/conformance' - cloudevent-builder-target: 'writeCloudEventDeclarative' - prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs14' - builder-runtime-version: '14' - nodejs16: + nodejs18: uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main with: http-builder-source: 'test/conformance' @@ -52,9 +22,10 @@ jobs: cloudevent-builder-source: 'test/conformance' cloudevent-builder-target: 'writeCloudEventDeclarative' prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs16' - builder-runtime-version: '16' - nodejs18: + builder-runtime: 'nodejs18' + builder-runtime-version: '18' + builder-url: 'us-docker.pkg.dev/serverless-runtimes/google-22-full/builder/nodejs:latest' + nodejs20: uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main with: http-builder-source: 'test/conformance' @@ -62,9 +33,10 @@ jobs: cloudevent-builder-source: 'test/conformance' cloudevent-builder-target: 'writeCloudEventDeclarative' prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs18' - builder-runtime-version: '18' - nodejs20: + builder-runtime: 'nodejs20' + builder-runtime-version: '20' + builder-url: 'us-docker.pkg.dev/serverless-runtimes/google-22-full/builder/nodejs:latest' + nodejs22: uses: GoogleCloudPlatform/functions-framework-conformance/.github/workflows/buildpack-integration-test.yml@main with: http-builder-source: 'test/conformance' @@ -72,5 +44,6 @@ jobs: cloudevent-builder-source: 'test/conformance' cloudevent-builder-target: 'writeCloudEventDeclarative' prerun: 'test/conformance/prerun.sh' - builder-runtime: 'nodejs20' - builder-runtime-version: '20' + builder-runtime: 'nodejs22' + builder-runtime-version: '22' + builder-url: 'us-docker.pkg.dev/serverless-runtimes/google-22-full/builder/nodejs:latest' diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index b4ba75c9..89c89f47 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [10, 12, 14, 16, 18, 20] + node-version: [18, 20, 22] steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e6e82099..eba94b65 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: - node-version: '14' + node-version: '20' - name: Install dependencies run: npm ci - name: Build docs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 26a4effc..a4e1baad 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,12 +25,12 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: - node-version: '16.x' + node-version: '20.x' - run: npm install - run: npm run build - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: - node-version: '16.x' + node-version: '20.x' registry-url: 'https://wombat-dressing-room.appspot.com' - id: publish env: diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 750bccb2..4e0337b4 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -11,7 +11,7 @@ jobs: test: strategy: matrix: - node-version: [10, 12, 14, 16, 18, 20] + node-version: [18, 20, 22] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: From d40a5149bd4302ecb293101a18f0eaa552ddfc7c Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Mon, 3 Feb 2025 15:14:37 +0100 Subject: [PATCH 4/5] fix(deps): downgrade @types/express to v4 --- package-lock.json | 48 +++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82460555..aab1905f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.4.6", "license": "Apache-2.0", "dependencies": { - "@types/express": "^5.0.0", + "@types/express": "^4.17.21", "body-parser": "^1.18.3", "cloudevents": "^8.0.2", "express": "^4.21.2", @@ -593,20 +593,22 @@ "dev": true }, "node_modules/@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", - "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -671,14 +673,16 @@ } }, "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==" + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" }, "node_modules/@types/semver": { "version": "7.5.8", @@ -6064,20 +6068,20 @@ "dev": true }, "@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-serve-static-core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", - "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -6142,9 +6146,9 @@ } }, "@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==" + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" }, "@types/range-parser": { "version": "1.2.7", diff --git a/package.json b/package.json index 21a892c2..830fce1b 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ } }, "dependencies": { - "@types/express": "^5.0.0", + "@types/express": "^4.17.21", "body-parser": "^1.18.3", "cloudevents": "^8.0.2", "express": "^4.21.2", From 356d2b09a15356977382b9136fca25b112a7dc44 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:14:54 +0000 Subject: [PATCH 5/5] chore(main): release 3.5.0 --- CHANGELOG.md | 12 ++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ad1f6d2..30ca69b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ [1]: https://www.npmjs.com/package/@google-cloud/functions-framework?activeTab=versions +## [3.5.0](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/compare/v3.4.6...v3.5.0) (2025-03-27) + + +### Features + +* adds a new ignored-routes config option ([70f68e9](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/commit/70f68e9d0b4fa1db6345ab012ddfec0fd983f762)) + + +### Bug Fixes + +* **deps:** downgrade @types/express to v4 ([d40a514](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/commit/d40a5149bd4302ecb293101a18f0eaa552ddfc7c)) + ## [3.4.6](https://github.com/GoogleCloudPlatform/functions-framework-nodejs/compare/v3.4.5...v3.4.6) (2025-03-04) diff --git a/package-lock.json b/package-lock.json index aab1905f..fb25b0aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@google-cloud/functions-framework", - "version": "3.4.6", + "version": "3.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@google-cloud/functions-framework", - "version": "3.4.6", + "version": "3.5.0", "license": "Apache-2.0", "dependencies": { "@types/express": "^4.17.21", diff --git a/package.json b/package.json index 830fce1b..5739ff0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@google-cloud/functions-framework", - "version": "3.4.6", + "version": "3.5.0", "description": "FaaS (Function as a service) framework for writing portable Node.js functions", "engines": { "node": ">=10.0.0"