Skip to content

Commit 1fc0e27

Browse files
committed
Allow CORS to be a parameter
1 parent 4559866 commit 1fc0e27

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

spec/v2/providers/https.spec.ts

+66
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { FULL_ENDPOINT, MINIMAL_V2_ENDPOINT, FULL_OPTIONS, FULL_TRIGGER } from "
3232
import { onInit } from "../../../src/v2/core";
3333
import { Handler } from "express";
3434
import { genkit } from "genkit";
35+
import { clearParams, defineList, Expression } from "../../../src/params";
3536

3637
function request(args: {
3738
data?: any;
@@ -227,6 +228,43 @@ describe("onRequest", () => {
227228
});
228229
});
229230

231+
it("should allow cors params", async () => {
232+
const origins = defineList("ORIGINS");
233+
234+
try {
235+
process.env.ORIGINS = '["example.com","example2.com"]';
236+
const func = https.onRequest(
237+
{
238+
cors: origins,
239+
},
240+
(req, res) => {
241+
res.send("42");
242+
}
243+
);
244+
const req = request({
245+
headers: {
246+
referrer: "example.com",
247+
"content-type": "application/json",
248+
origin: "example.com",
249+
},
250+
method: "OPTIONS",
251+
});
252+
253+
const response = await runHandler(func, req);
254+
255+
expect(response.status).to.equal(204);
256+
expect(response.headers).to.deep.equal({
257+
"Access-Control-Allow-Origin": "example.com",
258+
"Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
259+
"Content-Length": "0",
260+
Vary: "Origin, Access-Control-Request-Headers",
261+
});
262+
} finally {
263+
delete process.env.ORIGINS;
264+
clearParams();
265+
}
266+
});
267+
230268
it("should add CORS headers if debug feature is enabled", async () => {
231269
sinon.stub(debug, "isDebugFeatureEnabled").withArgs("enableCors").returns(true);
232270

@@ -301,13 +339,19 @@ describe("onRequest", () => {
301339
});
302340

303341
describe("onCall", () => {
342+
let origins: Expression<string[]>;
304343
beforeEach(() => {
344+
origins = defineList("ORIGINS");
345+
process.env.ORIGINS = '["example.com","example2.com"]';
346+
305347
options.setGlobalOptions({});
306348
process.env.GCLOUD_PROJECT = "aProject";
307349
});
308350

309351
afterEach(() => {
310352
delete process.env.GCLOUD_PROJECT;
353+
delete process.env.ORIGINS;
354+
clearParams();
311355
});
312356

313357
it("should return a minimal trigger/endpoint with appropriate values", () => {
@@ -441,6 +485,28 @@ describe("onCall", () => {
441485
});
442486
});
443487

488+
it("should allow cors params", async () => {
489+
const func = https.onCall({ cors: origins }, () => 42);
490+
const req = request({
491+
headers: {
492+
referrer: "example.com",
493+
"content-type": "application/json",
494+
origin: "example.com",
495+
},
496+
method: "OPTIONS",
497+
});
498+
499+
const response = await runHandler(func, req);
500+
501+
expect(response.status).to.equal(204);
502+
expect(response.headers).to.deep.equal({
503+
"Access-Control-Allow-Origin": "example.com",
504+
"Access-Control-Allow-Methods": "POST",
505+
"Content-Length": "0",
506+
Vary: "Origin, Access-Control-Request-Headers",
507+
});
508+
});
509+
444510
it("overrides CORS headers if debug feature is enabled", async () => {
445511
sinon.stub(debug, "isDebugFeatureEnabled").withArgs("enableCors").returns(true);
446512

src/v2/providers/https.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@ export interface HttpsOptions extends Omit<GlobalOptions, "region" | "enforceApp
7272
* If this is an `Array`, allows requests from domains matching at least one entry of the array.
7373
* Defaults to true for {@link https.CallableFunction} and false otherwise.
7474
*/
75-
cors?: string | boolean | RegExp | Array<string | RegExp>;
75+
cors?:
76+
| string
77+
| Expression<string>
78+
| Expression<string[]>
79+
| boolean
80+
| RegExp
81+
| Array<string | RegExp>;
7682

7783
/**
7884
* Amount of memory to allocate to a function.
@@ -314,7 +320,7 @@ export function onRequest(
314320
}
315321

316322
if (isDebugFeatureEnabled("enableCors") || "cors" in opts) {
317-
let origin = opts.cors;
323+
let origin = opts.cors instanceof Expression ? opts.cors.value() : opts.cors;
318324
if (isDebugFeatureEnabled("enableCors")) {
319325
// Respect `cors: false` to turn off cors even if debug feature is enabled.
320326
origin = opts.cors === false ? false : true;
@@ -424,7 +430,18 @@ export function onCall<T = any, Return = any | Promise<any>, Stream = unknown>(
424430
opts = optsOrHandler as CallableOptions;
425431
}
426432

427-
let origin = isDebugFeatureEnabled("enableCors") ? true : "cors" in opts ? opts.cors : true;
433+
let cors: string | boolean | RegExp | Array<string | RegExp> | undefined;
434+
if ("cors" in opts) {
435+
if (opts.cors instanceof Expression) {
436+
cors = opts.cors.value();
437+
} else {
438+
cors = opts.cors;
439+
}
440+
} else {
441+
cors = true;
442+
}
443+
444+
let origin = isDebugFeatureEnabled("enableCors") ? true : cors;
428445
// Arrays cause the access-control-allow-origin header to be dynamic based
429446
// on the origin header of the request. If there is only one element in the
430447
// array, this is unnecessary.

0 commit comments

Comments
 (0)