diff --git a/docs/docs/04-standard-library/cloud/api.md b/docs/docs/04-standard-library/cloud/api.md index eee75ac46aa..42399e40325 100644 --- a/docs/docs/04-standard-library/cloud/api.md +++ b/docs/docs/04-standard-library/cloud/api.md @@ -521,7 +521,7 @@ let ApiCorsOptions = cloud.ApiCorsOptions{ ... }; | allowCredentials | bool | Whether to allow credentials. | | allowHeaders | MutArray<str> | The list of allowed headers. | | allowMethods | MutArray<HttpMethod> | The list of allowed methods. | -| allowOrigin | MutArray<str> | The list of allowed allowOrigin. | +| allowOrigin | str | The allowed origin. | | exposeHeaders | MutArray<str> | The list of exposed headers. | | maxAge | duration | How long the browser should cache preflight request results. | @@ -583,20 +583,20 @@ The list of allowed methods. ##### `allowOrigin`Optional ```wing -allowOrigin: MutArray; +allowOrigin: str; ``` -- *Type:* MutArray<str> -- *Default:* ["*"] +- *Type:* str +- *Default:* "*" -The list of allowed allowOrigin. +The allowed origin. --- *Example* ```wing -["https://example.com"] +"https://example.com" ``` @@ -763,7 +763,7 @@ corsOptions: ApiCorsOptions; ``` - *Type:* ApiCorsOptions -- *Default:* Default CORS options are applied when `cors` is set to `true` allowOrigin: ["*"], allowMethods: [ HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.OPTIONS, ], allowHeaders: ["Content-Type", "Authorization"], exposeHeaders: [], allowCredentials: false, +- *Default:* Default CORS options are applied when `cors` is set to `true` allowOrigin: "*", allowMethods: [ HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.OPTIONS, ], allowHeaders: ["Content-Type", "Authorization"], exposeHeaders: [], allowCredentials: false, Options for configuring the API's CORS behavior across all routes. @@ -774,7 +774,7 @@ Options can also be overridden on a per-route basis. (not yet implemented) *Example* ```wing -{ allowOrigin: ["https://example.com"] } +{ allowOrigin: "https://example.com" } ``` diff --git a/examples/tests/valid/api_cors_custom.test.w b/examples/tests/valid/api_cors_custom.test.w index 6abf47e2b11..20b71b971e5 100644 --- a/examples/tests/valid/api_cors_custom.test.w +++ b/examples/tests/valid/api_cors_custom.test.w @@ -6,7 +6,7 @@ bring expect; let api = new cloud.Api( cors: true, corsOptions: { - allowOrigin: ["winglang.io"], + allowOrigin: "winglang.io", allowMethods: [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], allowHeaders: ["Content-Type", "Authorization", "X-Custom-Header"], allowCredentials: true, @@ -70,4 +70,4 @@ test "OPTIONS /users responds with proper headers for requested" { expect.equal(headers.tryGet("access-control-allow-methods"), "GET,POST,OPTIONS"); expect.equal(headers.tryGet("access-control-allow-headers"), "Content-Type,Authorization,X-Custom-Header"); expect.equal(headers.tryGet("access-control-allow-origin"), "winglang.io"); -} \ No newline at end of file +} diff --git a/examples/tests/valid/website_with_api.test.w b/examples/tests/valid/website_with_api.test.w index 4f2223b3363..5590e5bd30e 100644 --- a/examples/tests/valid/website_with_api.test.w +++ b/examples/tests/valid/website_with_api.test.w @@ -7,7 +7,7 @@ bring expect; let api = new cloud.Api( cors: true, corsOptions: cloud.ApiCorsOptions { - allowOrigin: ["*"], + allowOrigin: "*", allowMethods: [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], allowHeaders: ["Content-Type"], allowCredentials: false, diff --git a/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap b/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap index d70c0c88493..a121951c269 100644 --- a/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap +++ b/libs/wingc/src/lsp/snapshots/completions/incomplete_inflight_namespace.snap @@ -95,7 +95,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `Array?` — The list of allowed allowOrigin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." + value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `str?` — The allowed origin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." sortText: hh|ApiCorsOptions - label: ApiDeleteOptions kind: 22 diff --git a/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap b/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap index d70c0c88493..a121951c269 100644 --- a/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap +++ b/libs/wingc/src/lsp/snapshots/completions/namespace_middle_dot.snap @@ -95,7 +95,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `Array?` — The list of allowed allowOrigin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." + value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `str?` — The allowed origin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." sortText: hh|ApiCorsOptions - label: ApiDeleteOptions kind: 22 diff --git a/libs/wingc/src/lsp/snapshots/completions/partial_type_reference_annotation.snap b/libs/wingc/src/lsp/snapshots/completions/partial_type_reference_annotation.snap index d70c0c88493..a121951c269 100644 --- a/libs/wingc/src/lsp/snapshots/completions/partial_type_reference_annotation.snap +++ b/libs/wingc/src/lsp/snapshots/completions/partial_type_reference_annotation.snap @@ -95,7 +95,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `Array?` — The list of allowed allowOrigin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." + value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `str?` — The allowed origin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." sortText: hh|ApiCorsOptions - label: ApiDeleteOptions kind: 22 diff --git a/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap b/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap index d70c0c88493..a121951c269 100644 --- a/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap +++ b/libs/wingc/src/lsp/snapshots/completions/variable_type_annotation_namespace.snap @@ -95,7 +95,7 @@ source: libs/wingc/src/lsp/completions.rs kind: 22 documentation: kind: markdown - value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `Array?` — The list of allowed allowOrigin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." + value: "```wing\nstruct ApiCorsOptions\n```\n---\nCors Options for `Api`.\n### Fields\n- `allowCredentials?` — `bool?` — Whether to allow credentials.\n- `allowHeaders?` — `Array?` — The list of allowed headers.\n- `allowMethods?` — `Array?` — The list of allowed methods.\n- `allowOrigin?` — `str?` — The allowed origin.\n- `exposeHeaders?` — `Array?` — The list of exposed headers.\n- `maxAge?` — `duration?` — How long the browser should cache preflight request results." sortText: hh|ApiCorsOptions - label: ApiDeleteOptions kind: 22 diff --git a/libs/wingsdk/src/cloud/api.ts b/libs/wingsdk/src/cloud/api.ts index 2ab8748ed58..8cd2fc62139 100644 --- a/libs/wingsdk/src/cloud/api.ts +++ b/libs/wingsdk/src/cloud/api.ts @@ -16,11 +16,11 @@ export const API_FQN = fqnForType("cloud.Api"); */ export interface ApiCorsOptions { /** - * The list of allowed allowOrigin. - * @example ["https://example.com"] - * @default - ["*"] + * The allowed origin. + * @example "https://example.com" + * @default - "*" */ - readonly allowOrigin?: Array; + readonly allowOrigin?: string; /** * The list of allowed methods. @@ -75,9 +75,9 @@ export interface ApiProps { * Options for configuring the API's CORS behavior across all routes. * Options can also be overridden on a per-route basis. (not yet implemented) * - * @example { allowOrigin: ["https://example.com"] } + * @example { allowOrigin: "https://example.com" } * @default - Default CORS options are applied when `cors` is set to `true` - * allowOrigin: ["*"], + * allowOrigin: "*", * allowMethods: [ * HttpMethod.GET, * HttpMethod.POST, @@ -209,7 +209,7 @@ export class Api extends Resource { }; private corsDefaultValues: ApiCorsOptions = { - allowOrigin: ["*"], + allowOrigin: "*", allowMethods: [ HttpMethod.GET, HttpMethod.POST, @@ -502,7 +502,7 @@ export class Api extends Resource { } const { - allowOrigin = [], + allowOrigin = "*", allowHeaders = [], allowMethods = [], exposeHeaders = [], @@ -511,13 +511,13 @@ export class Api extends Resource { } = corsOptions; const defaultHeaders: CorsDefaultResponseHeaders = { - "Access-Control-Allow-Origin": allowOrigin.join(",") || "", + "Access-Control-Allow-Origin": allowOrigin || "*", "Access-Control-Expose-Headers": exposeHeaders.join(",") || "", "Access-Control-Allow-Credentials": allowCredentials ? "true" : "false", }; const optionsHeaders: CorsOptionsResponseHeaders = { - "Access-Control-Allow-Origin": allowOrigin.join(",") || "", + "Access-Control-Allow-Origin": allowOrigin || "*", "Access-Control-Allow-Headers": allowHeaders.join(",") || "", "Access-Control-Allow-Methods": allowMethods.join(",") || "", "Access-Control-Max-Age": maxAge.seconds.toString(), diff --git a/libs/wingsdk/test/target-sim/api.test.ts b/libs/wingsdk/test/target-sim/api.test.ts index 52e64f20ca9..9474e18578d 100644 --- a/libs/wingsdk/test/target-sim/api.test.ts +++ b/libs/wingsdk/test/target-sim/api.test.ts @@ -669,7 +669,7 @@ test("api with custom CORS settings", async () => { const api = new cloud.Api(app, "my_api", { cors: true, corsOptions: { - allowOrigin: ["https://example.com"], + allowOrigin: "https://example.com", allowCredentials: true, exposeHeaders: ["x-wingnuts"], }, diff --git a/tools/hangar/__snapshots__/test_corpus/valid/api_cors_custom.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/api_cors_custom.test.w_compile_tf-aws.md index fbb8a9e0e3a..a855ebae484 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/api_cors_custom.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/api_cors_custom.test.w_compile_tf-aws.md @@ -484,7 +484,7 @@ class $Root extends $stdlib.std.Resource { }); } } - const api = this.node.root.new("@winglang/sdk.cloud.Api", cloud.Api, this, "cloud.Api", { cors: true, corsOptions: ({"allowOrigin": ["winglang.io"], "allowMethods": [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], "allowHeaders": ["Content-Type", "Authorization", "X-Custom-Header"], "allowCredentials": true, "exposeHeaders": ["Content-Type"]}) }); + const api = this.node.root.new("@winglang/sdk.cloud.Api", cloud.Api, this, "cloud.Api", { cors: true, corsOptions: ({"allowOrigin": "winglang.io", "allowMethods": [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], "allowHeaders": ["Content-Type", "Authorization", "X-Custom-Header"], "allowCredentials": true, "exposeHeaders": ["Content-Type"]}) }); (api.get("/users", new $Closure1(this, "$Closure1"))); this.node.root.new("@winglang/sdk.std.Test", std.Test, this, "test:GET /users has cors headers", new $Closure2(this, "$Closure2")); this.node.root.new("@winglang/sdk.std.Test", std.Test, this, "test:OPTIONS /users has cors headers", new $Closure3(this, "$Closure3")); diff --git a/tools/hangar/__snapshots__/test_corpus/valid/website_with_api.test.w_compile_tf-aws.md b/tools/hangar/__snapshots__/test_corpus/valid/website_with_api.test.w_compile_tf-aws.md index 1a701c26b29..ed042e83088 100644 --- a/tools/hangar/__snapshots__/test_corpus/valid/website_with_api.test.w_compile_tf-aws.md +++ b/tools/hangar/__snapshots__/test_corpus/valid/website_with_api.test.w_compile_tf-aws.md @@ -783,7 +783,7 @@ class $Root extends $stdlib.std.Resource { }); } } - const api = this.node.root.new("@winglang/sdk.cloud.Api", cloud.Api, this, "cloud.Api", { cors: true, corsOptions: ({"allowOrigin": ["*"], "allowMethods": [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], "allowHeaders": ["Content-Type"], "allowCredentials": false, "exposeHeaders": ["Content-Type"], "maxAge": (std.Duration.fromSeconds(600))}) }); + const api = this.node.root.new("@winglang/sdk.cloud.Api", cloud.Api, this, "cloud.Api", { cors: true, corsOptions: ({"allowOrigin": "*", "allowMethods": [cloud.HttpMethod.GET, cloud.HttpMethod.POST, cloud.HttpMethod.OPTIONS], "allowHeaders": ["Content-Type"], "allowCredentials": false, "exposeHeaders": ["Content-Type"], "maxAge": (std.Duration.fromSeconds(600))}) }); const website = this.node.root.new("@winglang/sdk.cloud.Website", cloud.Website, this, "cloud.Website", { path: "./website_with_api" }); const usersTable = this.node.root.new("@winglang/sdk.ex.Table", ex.Table, this, "ex.Table", { name: "users-table", primaryKey: "id", columns: ({["id"]: ex.ColumnType.STRING, ["name"]: ex.ColumnType.STRING, ["age"]: ex.ColumnType.NUMBER}) }); const getHandler = new $Closure1(this, "$Closure1");