Skip to content

Commit

Permalink
Merge of #2904
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Sep 6, 2023
2 parents 4b79589 + f537c8b commit 9de9b53
Show file tree
Hide file tree
Showing 49 changed files with 4,713 additions and 272 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules/

.pnpm-store/

# Terraform state files
*.tfstate
*.tfstate.*
Expand Down
171 changes: 171 additions & 0 deletions docs/docs/04-standard-library/01-cloud/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,123 @@ let ApiConnectProps = cloud.ApiConnectProps{ ... };
```
### ApiCorsOptions <a name="ApiCorsOptions" id="@winglang/sdk.cloud.ApiCorsOptions"></a>
Cors Options for `Api`.
#### Initializer <a name="Initializer" id="@winglang/sdk.cloud.ApiCorsOptions.Initializer"></a>
```wing
bring cloud;

let ApiCorsOptions = cloud.ApiCorsOptions{ ... };
```
#### Properties <a name="Properties" id="Properties"></a>
| **Name** | **Type** | **Description** |
| --- | --- | --- |
| <code><a href="#@winglang/sdk.cloud.ApiCorsOptions.property.allowCredentials">allowCredentials</a></code> | <code>bool</code> | Whether to allow credentials. |
| <code><a href="#@winglang/sdk.cloud.ApiCorsOptions.property.allowHeaders">allowHeaders</a></code> | <code>MutArray&lt;str&gt;</code> | The list of allowed headers. |
| <code><a href="#@winglang/sdk.cloud.ApiCorsOptions.property.allowMethods">allowMethods</a></code> | <code>MutArray&lt;<a href="#@winglang/sdk.cloud.HttpMethod">HttpMethod</a>&gt;</code> | The list of allowed methods. |
| <code><a href="#@winglang/sdk.cloud.ApiCorsOptions.property.allowOrigin">allowOrigin</a></code> | <code>MutArray&lt;str&gt;</code> | The list of allowed allowOrigin. |
| <code><a href="#@winglang/sdk.cloud.ApiCorsOptions.property.exposeHeaders">exposeHeaders</a></code> | <code>MutArray&lt;str&gt;</code> | The list of exposed headers. |
---
##### `allowCredentials`<sup>Optional</sup> <a name="allowCredentials" id="@winglang/sdk.cloud.ApiCorsOptions.property.allowCredentials"></a>
```wing
allowCredentials: bool;
```
- *Type:* bool
- *Default:* false
Whether to allow credentials.
---
##### `allowHeaders`<sup>Optional</sup> <a name="allowHeaders" id="@winglang/sdk.cloud.ApiCorsOptions.property.allowHeaders"></a>
```wing
allowHeaders: MutArray<str>;
```
- *Type:* MutArray&lt;str&gt;
- *Default:* ["Content-Type", "Authorization"]
The list of allowed headers.
---
*Example*
```wing
["Content-Type"]
```
##### `allowMethods`<sup>Optional</sup> <a name="allowMethods" id="@winglang/sdk.cloud.ApiCorsOptions.property.allowMethods"></a>
```wing
allowMethods: MutArray<HttpMethod>;
```
- *Type:* MutArray&lt;<a href="#@winglang/sdk.cloud.HttpMethod">HttpMethod</a>&gt;
- *Default:* [HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE, HttpMethod.HEAD, HttpMethod.OPTIONS]
The list of allowed methods.
---
*Example*
```wing
[HttpMethod.GET, HttpMethod.POST]
```
##### `allowOrigin`<sup>Optional</sup> <a name="allowOrigin" id="@winglang/sdk.cloud.ApiCorsOptions.property.allowOrigin"></a>
```wing
allowOrigin: MutArray<str>;
```
- *Type:* MutArray&lt;str&gt;
- *Default:* ["*"]
The list of allowed allowOrigin.
---
*Example*
```wing
["https://example.com"]
```
##### `exposeHeaders`<sup>Optional</sup> <a name="exposeHeaders" id="@winglang/sdk.cloud.ApiCorsOptions.property.exposeHeaders"></a>
```wing
exposeHeaders: MutArray<str>;
```
- *Type:* MutArray&lt;str&gt;
- *Default:* []
The list of exposed headers.
---
*Example*
```wing
["Content-Type"]
```
### ApiDeleteProps <a name="ApiDeleteProps" id="@winglang/sdk.cloud.ApiDeleteProps"></a>
Options for Api put endpoint.
Expand Down Expand Up @@ -557,6 +674,60 @@ bring cloud;
let ApiProps = cloud.ApiProps{ ... };
```
#### Properties <a name="Properties" id="Properties"></a>
| **Name** | **Type** | **Description** |
| --- | --- | --- |
| <code><a href="#@winglang/sdk.cloud.ApiProps.property.cors">cors</a></code> | <code>bool</code> | Options for configuring the API's CORS behavior across all routes. |
| <code><a href="#@winglang/sdk.cloud.ApiProps.property.corsOptions">corsOptions</a></code> | <code><a href="#@winglang/sdk.cloud.ApiCorsOptions">ApiCorsOptions</a></code> | Options for configuring the API's CORS behavior across all routes. |
---
##### `cors`<sup>Optional</sup> <a name="cors" id="@winglang/sdk.cloud.ApiProps.property.cors"></a>
```wing
cors: bool;
```
- *Type:* bool
- *Default:* false, CORS configuration is disabled
Options for configuring the API's CORS behavior across all routes.
Options can also be overridden on a per-route basis. (not yet implemented)
When enabled this will add CORS headers with default options.
Can be customized by passing `corsOptions`
---
*Example*
```wing
true
```
##### `corsOptions`<sup>Optional</sup> <a name="corsOptions" id="@winglang/sdk.cloud.ApiProps.property.corsOptions"></a>
```wing
corsOptions: ApiCorsOptions;
```
- *Type:* <a href="#@winglang/sdk.cloud.ApiCorsOptions">ApiCorsOptions</a>
- *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.
Options can also be overridden on a per-route basis. (not yet implemented)
---
*Example*
```wing
{ allowOrigin: ["https://example.com"] }
```
### ApiPutProps <a name="ApiPutProps" id="@winglang/sdk.cloud.ApiPutProps"></a>
Expand Down
22 changes: 22 additions & 0 deletions examples/tests/sdk_tests/api/cors.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
bring cloud;
bring http;
bring util;

let api = new cloud.Api({
cors: true
});
let body = "ok!";

api.get("/path", inflight (req) => {
return {
status: 200,
body: body
};
});

test "http.get and http.fetch can preform a call to an api" {
let url = api.url + "/path";
let response = http.get(url);

assert(response.headers.get("access-control-allow-origin") == "*");
}
73 changes: 73 additions & 0 deletions examples/tests/valid/api_cors_custom.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
bring cloud;
bring ex;
bring http;
bring "./assertions.w" as t;

let api = new 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", inflight (req) => {
return {
body: "hello world",
status: 200
};
});

test "GET /users has cors headers" {
let response = http.get(api.url + "/users");

let headers = response.headers;
t.Assert.equalNum(response.status, 200);

// GET cors headers are set
t.Assert.equalStr(headers.get("access-control-allow-origin"), "winglang.io");
t.Assert.equalStr(headers.get("access-control-allow-credentials"), "true");
t.Assert.equalStr(headers.get("access-control-expose-headers"), "Content-Type");

// OPTIONS cors headers are not set
t.Assert.isNil(headers.get("access-control-allow-headers"));
t.Assert.isNil(headers.get("access-control-allow-methods"));
}

test "OPTIONS /users has cors headers" {
let response = http.fetch(api.url + "/users", {
method: http.HttpMethod.OPTIONS
});

let headers = response.headers;

t.Assert.equalNum(response.status, 204);

// OPTIONS cors headers are set
t.Assert.equalStr(headers.get("access-control-allow-methods"), "GET,POST,OPTIONS");
t.Assert.equalStr(headers.get("access-control-allow-headers"), "Content-Type,Authorization,X-Custom-Header");
t.Assert.equalStr(headers.get("access-control-allow-origin"), "winglang.io");

// Other cors headers are not set
t.Assert.isNil(headers.get("access-control-expose-headers"));
t.Assert.isNil(headers.get("access-control-allow-credentials"));
}

test "OPTIONS /users responds with proper headers for requested" {
let response = http.fetch(api.url + "/users", {
method: http.HttpMethod.OPTIONS,
headers: {
"Access-Control-Request-Method": "PUT",
"Access-Control-Request-Headers": "Content-Type,Authorization,X-Custom-Foo",
}
});

let headers = response.headers;
t.Assert.equalNum(response.status, 204);
t.Assert.equalStr(headers.get("access-control-allow-methods"), "GET,POST,OPTIONS");
t.Assert.equalStr(headers.get("access-control-allow-headers"), "Content-Type,Authorization,X-Custom-Header");
t.Assert.equalStr(headers.get("access-control-allow-origin"), "winglang.io");
}
50 changes: 50 additions & 0 deletions examples/tests/valid/api_cors_default.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
bring cloud;
bring ex;
bring http;
bring "./assertions.w" as t;

let apiDefaultCors = new cloud.Api(
cors: true
);

apiDefaultCors.get("/users", inflight (req) => {
return {
body: "hello world",
status: 200
};
});

test "GET /users has default cors headers" {
let response = http.get(apiDefaultCors.url + "/users");

let headers = response.headers;
t.Assert.equalNum(response.status, 200);

// GET cors headers are set
t.Assert.equalStr(headers.get("access-control-allow-origin"), "*");
t.Assert.equalStr(headers.get("access-control-allow-credentials"), "false");
t.Assert.equalStr(headers.get("access-control-expose-headers"), "");

// OPTIONS headers are not set
t.Assert.isNil(headers.get("access-control-allow-headers"));
t.Assert.isNil(headers.get("access-control-allow-methods"));
}

test "OPTIONS /users has default cors headers" {
let response = http.fetch(apiDefaultCors.url + "/users", {
method: http.HttpMethod.OPTIONS
});

let headers = response.headers;
t.Assert.equalNum(response.status, 204);

// OPTIONS cors headers are set
t.Assert.equalStr(headers.get("access-control-allow-headers"), "Content-Type,Authorization,X-Requested-With");
t.Assert.equalStr(headers.get("access-control-allow-methods"), "GET,POST,PUT,DELETE,HEAD,OPTIONS");
t.Assert.equalStr(headers.get("access-control-allow-origin"), "*");

// Other headers are not set
t.Assert.isNil(headers.get("access-control-allow-credentials"));
t.Assert.isNil(headers.get("access-control-expose-headers"));
}

27 changes: 27 additions & 0 deletions examples/tests/valid/assertions.w
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
inflight class Assert {
static equalStr(a: str, b: str): bool {
try {
assert(a == b);
} catch e {
throw("expected: ${b} got: ${a}");
}
}

static isNil(a: str?): bool {
try {
assert(a == nil);
} catch e {
log(e);
throw("expected '${a}' to be nil");
}
}

static equalNum(a: num, b: num): bool{
try {
assert(a == b);
} catch e {
log(e);
throw("expected: ${b} got: ${a}");
}
}
}
Loading

0 comments on commit 9de9b53

Please sign in to comment.