> For the complete documentation index, see [llms.txt](https://greymatter.gitbook.io/grey-matter-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://greymatter.gitbook.io/grey-matter-documentation/usage/fabric/api/domain/cors_config.md).

# CORS

## Summary

Grey Matter supports the configuration of cross-origin resource sharing on a sidecar. CORS can be configured to allow an application to access resources at a different origin (domain, protocol, or port) than its own.

For more information on CORS, see this [CORS reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).

### Simple Requests

Simple requests are classified as requests that don't require a [CORS preflight check](/grey-matter-documentation/usage/fabric/api/domain/cors_config.md#preflight-requests). This distinction is made between requests that might be dangerous (i.e. modifies server resources) and those that are most likely benign. A request is considered simple when *all* of the following criteria is true:

* The method is `GET`, `HEAD`, or `POST`
* Only [CORS safe-listed headers](https://fetch.spec.whatwg.org/#cors-safelisted-request-header) are present
* The `Content Type` header is set to one of `application/x-www-form-urlencoded` or `multipart/form-data` or `text/plain`

A more comprehensive list and explanation can be found [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple-requests).

As an example, say an app running at `http://localhost:8080` is trying to call a backend service with a Grey Matter sidecar at `http://localhost:10808`. Without a CORS configuration, this request would fail, because the app `localhost:8080` is trying to access resources from a server at a different origin, `localhost:10808`. To solve this, the following CORS config is set on its domain:

```javascript
{
  "zone_key": "zone-default-zone",
  "domain_key": "domain-backend-service",
  "name": "*",
  "port": 10808,
  "cors_config": {
    "allowed_origins": [
      { "match_type": "exact", "value": "http://localhost:8080" }
    ],
    "allowed_headers": [],
    "allowed_methods": [],
    "exposed_headers": [],
    "max_age": 60
  }
}
```

With this configuration, if a simple request comes in to the sidecar from the app, it will have an `Origin` header value of `http://localhost:8080`, and this request will succeed. The server will attach a header `Access-Control-Allow-Origin: http://localhost:8080` to the response, which signals to the browser that this request is allowed.

### Preflight Requests

[Preflight requests](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) are initiated by the browser using the `OPTIONS` HTTP method before sending a request in order to determine if the real request is safe to send. The response to this kind of request contains information about what is allowed from a request, and the server determines whether or not to send the actual request based on this information.

This response information is in the form of three HTTP headers, `access-control-request-method`, `access-control-request-headers`, and the `origin` header. These correspond to [fields](/grey-matter-documentation/usage/fabric/api/domain/cors_config.md#fields) of the `cors_config` - thus these configurations can be specified to determine how the Grey Matter sidecar will respond to preflight requests. If a preflight request comes in to the Grey Matter Sidecar that does not meet the specification for one of these configured fields, the sidecar will send back a response to not initiate the request.

Based on the same [example from simple requests](/grey-matter-documentation/usage/fabric/api/domain/cors_config.md#simple-requests), say the app running at `http://localhost:8080` wants to send requests to the backend service at `http://localhost:10808` with a content-type of `application/json;charset=UTF-8`. This particular content-type is outside of those allowed by CORS for simple requests, and thus would result in sending a preflight request to determine if the request can be sent. In order for the CORS configuration to indicate that the request can be sent, it would need to allow the `content-type` header by configuring the [`allowed_headers`](/grey-matter-documentation/usage/fabric/api/domain/cors_config.md#allowed_headers) field:

```javascript
{
  "zone_key": "zone-default-zone",
  "domain_key": "domain-backend-service",
  "name": "*",
  "port": 10808,
  "cors_config": {
    "allowed_origins": [
      { "match_type": "exact", "value": "http://localhost:8080" }
    ],
    "allowed_headers": ["content-type"],
    "allowed_methods": [],
    "exposed_headers": [],
    "max_age": 60
  }
}
```

In the above configuration, CORS will allow requests with `Origin` header value `http://localhost:8080` only *and* indicate that the content-type header can be set according to the request.

### Configuration

To set up CORS, set the `cors_config` field on a domain object with the desired configuration, see the [fields](/grey-matter-documentation/usage/fabric/api/domain/cors_config.md#fields) below.

For an existing domain, run

```bash
greymatter edit domain <domain-name>
```

and add the desired `cors_config` object.

### Example object

```javascript
  "cors_config": {
    "allowed_origins": [],
    "allowed_headers": [],
    "allowed_methods": [],
    "exposed_headers": [],
    "max_age": 0,
    "allow_credentials": true
  }
```

### Fields

#### `allowed_origins`

This field specifies an array of string patterns that match allowed origins. The proxy will use these matchers to set the [`access-control-allow-origin`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) header. This header will be set on any cross-origin response that matches one of the `allowed_origins`.

Available matchers include:

* `exact`
* `prefix`
* `suffix`
* `regex`

Example:

```javascript
  "allowed_origins": [
      { "match_type": "exact", "value": "http://localhost:8080" }
    ]
```

A wildcard value `*` is allowed except when using the `regex` matcher.

#### `allow_credentials`

Specifies the content for the [`access-control-allow-credentials`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials) header that the proxy will set on any cross-origin request that matches one of the `allowed_origins`. This header specifies whether or not the upstream service allows credentials.

#### `exposed_headers`

Specifies the content for the [`access-control-expose-headers`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers) header that the proxy will set on any cross-origin request that matches one of the `allowed_origins`. This header specifies an array of headers that are allowed on the response.

#### `max_age`

Specifies the content for the [`access-control-max-age`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age) header that the proxy will set on the preflight response. This header is an integer value specifying how long a preflight request can be cached by the browser.

#### `allowed_methods`

Specifies the content for the [`access-control-allow-methods`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods) header that the proxy will set on the preflight response. This header specifies an array of methods allowed by the upstream service.

#### `allowed_headers`

Specifies the content for the [`access-control-allow-headers`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers) header that the proxy will set on the preflight response. This header specifies an array of headers allowed by the upstream service.

### Notes

* By default, the proxy will use the upstream service's CORS policy on the gateway **and** on the upstream service. The gateway policy is ignored.
* Because CORS is a browser construct, curl can always make a request to the server, with or without CORS. However, it can be used to mimic a browser and verify how the proxy will react to CORS requests:

```bash
$ curl -v 'http://localhost:9080/services/catalog/latest/' \
    -X OPTIONS \
    -H 'Access-Control-Request-Method: POST' \
    -H 'Access-Control-Request-Headers: content-type' \
    -H 'Origin: http://localhost:8080'
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9080 (#0)
> OPTIONS /services/catalog/latest/ HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.64.1
> Accept: */*
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: content-type
> Origin: http://localhost:8080
>
< HTTP/1.1 200 OK
< access-control-allow-origin: http://localhost:8080
< access-control-max-age: 60
< date: Tue, 12 May 2020 20:11:13 GMT
< server: envoy
< content-length: 0
<
* Connection #0 to host localhost left intact
* Closing connection 0
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://greymatter.gitbook.io/grey-matter-documentation/usage/fabric/api/domain/cors_config.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
