1. Cross-origin resource access: Security risks and browser limits
If a resource on a server requests another resource that is deployed in a different domain or uses a different port, the former resource sends a cross-origin HTTP request. For example, an HTML page from the site http://www.aliyun.com sends a request for an image whose URL is http://www.alibaba.com/image.jpg. Most web pages on the Internet support loading resources, such as CSS, images, and scripts, from different domains.
For security reasons, most browsers forbid sending cross-origin requests from web scripts. Other browsers allow you to send cross-origin requests but responses are blocked. This means that when a web application calls an API operation, only the relevant resources in the same domain can be loaded. To load resources from a different domain, you must configure cross-origin resource sharing (CORS) for the API operation. In this way, the destination server where the requested resource resides will authorize the cross-origin request.

The preceding figure shows a typical scenario of cross-origin resource access. By default, mainstream browsers forbid cross-origin resource access for security reasons. However, these browsers support the CORS mechanism that is recommended by the World Wide Web Consortium (W3C). The CORS mechanism is implemented based on a server and a browser. By using this mechanism, you can enable the browser to allow cross-origin requests.

2. CORS overview
2.1 Two request validation modes
The CORS mechanism supports two request validation modes: simple request validation and preflighted request validation.
If a cross-origin request meets all of the following three conditions, the CORS mechanism uses simple request validation to process the cross-origin request.
1. The cross-origin request uses one of the following methods:
GET
HEAD
POST
2. The Content-Type header field in the cross-origin request is set to one of the following values:
application/x-www-form-urlencoded
multipart/form-data
text/plain
3. The following CORS header fields, including custom header fields in the cross-origin request, are defined in the Fetch standard:
Accept
Accept-Language
Content-Language
Content-Type (Note that this header field must be set to one of the values that are listed in the second condition.)
DPR
Downlink
Save-Data
Viewport-Width
Width
If a cross-origin request does not meet all of the preceding conditions, the CORS mechanism uses preflighted request validation to process the cross-origin request.
2.2 Simple request validation
In the simple request validation mode, a browser sends a cross-origin request. The Origin header field is specified in the request, indicating that the request is a cross-origin request. After the destination server, where the requested resource resides, receives the cross-origin request, the server determines whether to validate the request based on configured CORS rules. If the validation is successful, the server returns a success response to the browser. The success response includes the Access-Control-Allow-Origin and Access-Control-Allow-Methods header fields. If the validation fails, the server returns an error response to the browser.
The success response includes the Access-Control-Allow-Origin header field. To sum up, in the simple request validation mode, a cross-origin request from a browser must include the Origin header field and a success response from the destination server must include the Access-Control-Allow-Origin header field. In this example, the value of the Access-Control-Allow-Origin header field in the success response is *, which indicates that the requested resource can be accessed from all domains. If the destination server allows cross-origin requests only from the site http://www.aliyun.com, the value of this header field must be specified as http://www.aliyun.com, as shown in the following code snippet:
Access-Control-Allow-Origin: http://www.aliyun.com
In this way, cross-origin requests only from the site http://www.aliyun.com are allowed by the destination server.
2.3 Preflighted request validation
In the preflighted request validation mode, after a browser constructs a cross-origin request, the cross-origin request is not immediately sent to the destination server. Instead, a preflighted request is sent to the destination server. The preflighted request is an HTTP OPTIONS request. This request is used to check whether the destination server, where the requested resource resides, allows cross-origin requests from the current domain name. If the response to the preflighted request indicates that the destination server allows cross-origin requests from the current domain name, the browser then sends the cross-origin request to the server.
The OPTIONS request contains the following header fields: Origin, Access-Control-Request-Method, and Access-Control-Request-Headers. After the destination server receives the OPTIONS request, the server determines whether to validate the preflighted request. If the validation is successful, the server specifies the Access-Control-Allow-Origin, Access-Control-Allow-Method, Access-Control-Allow-Headers, and Access-Control-Max-Age header fields in the success response. After the browser receives the success response to the preflighted request, the browser sends the cross-origin request.
The Access-Control-Request-Method header field in the OPTIONS request informs the destination server that the cross-origin request to be sent uses the GET method. The Access-Control-Request-Headers header field in the OPTIONS request informs the destination server that the cross-origin request to be sent contains two custom header fields: X-Ca-Nonce and Content-Type. Based on these two header fields in the OPTIONS request, the destination server determines whether to allow the cross-origin request.
The Access-Control-Allow-Methods header field in the success response to the OPTIONS request indicates that the destination server allows a cross-origin request from the browser to use the GET method. If multiple methods are allowed, the methods are separated with commas (,).
The Access-Control-Allow-Headers header field in the success response to the OPTIONS request indicates that the destination server allows a cross-origin request to contain the X-Ca-Nonce and Content-Type header fields. The header fields are separated with commas (,).
The Access-Control-Max-Age header field in the success response to the OPTIONS request indicates that the response is valid for 86,400 seconds, namely, 24 hours. Within this validity period, if the browser needs to send the same cross-origin request again, the browser does not need to send another preflighted request. Note that the browser itself specifies a validity period for the cross-origin request. If the value of the Access-Control-Max-Age header field exceeds the validity period that is specified by the browser, the Access-Control-Max-Age header field will not take effect.
3. Implement the CORS mechanism in API Gateway
3.1 Configure the simple request validation mode
By default, all API operations in API Gateway support cross-origin calls. Therefore, by default, API Gateway adds the Access-Control-Allow-Origin header field and specifies its value as * in each API response. The following code snippets show an example of this process:
An API request from a client
GET /simple HTTP/1.1
Host: www.alibaba.com
orgin: http://www.aliyun.com
content-type: application/x-www-form-urlencoded; charset=utf-8
accept: application/json; charset=utf-8
date: Mon, 18 Sep 2017 09:53:23 GMT
The response that is sent from the backend service of the API operation to API Gateway
HTTP/1.1 200 OK
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}
The response that is sent from API Gateway to the client
HTTP/1.1 200 OK
Date: Mon, 18 Sep 2017 09:53:23 GMT
Access-Control-Allow-Origin: *
X-Ca-Request-Id: 104735BD-8968-458F-9929-DBFA43F324C6
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}
As shown in the preceding code snippets, API Gateway adds specific information to the response that is sent from the backend service, including the following information:
Access-Control-Allow-Origin: *
API Gateway specifies the Access-Control-Allow-Origin header field as *, which indicates that the API operation can be called from all domains.
If you need to specify the Access-Control-Allow-Origin header field as another value, add the Access-Control-Allow-Origin header field as a response header field when you configure response information for the API operation. The custom value of the Access-Control-Allow-Origin header field will override the default value. The following code snippets show an example in which an API operation can be called only from the site http://www.aliyun.com:
An API request from a client
GET /simple HTTP/1.1
Host: www.alibaba.com
orgin: http://www.aliyun.com
content-type: application/x-www-form-urlencoded; charset=utf-8
accept: application/json; charset=utf-8
date: Mon, 18 Sep 2017 09:53:23 GMT
The response that is sent from the backend service of the API operation to API Gateway
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.aliyun.com
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}
The response that is sent from API Gateway to the client
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.aliyun.com
X-Ca-Request-Id: 104735BD-8968-458F-9929-DBFA43F324C6
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}
3.2 Configure the preflighted request validation mode
API Gateway allows you to set the HTTP request method of an API operation to OPTIONS. In this case, API Gateway will directly pass each OPTIONS request to the backend service of the API operation. When you create an API operation that allows only OPTIONS requests, take note of the following items:
When you configure basic information for the API operation, set Security Certification to No Certification.
When you configure request information for the API operation, enter / in the Request Path field and select the Match All Child Paths check box. After you set HTTP Method to OPTIONS, the Request Mode parameter is automatically set to Request Parameter Passthrough and cannot be modified. You do not need to define request parameters for the API operation.
For each API group, you can create an API operation that allows only OPTIONS requests and use this API operation to configure CORS policies for the API group. You can use curl to test HTTP requests for the API operation that allows only OPTIONS requests. The following code snippet shows an example of using curl to call the API operation:
sudo curl -X OPTIONS -H "Access-Control-Request-Method:POST" -H "Access-Control-Request-Headers:X-CUSTOM-HEADER" http://ec12ac094e734544be02c928366b7b26-cn-qingdao.alicloudapi.com/optinstest -i
HTTP/1.1 200 OK
Server: Tengine
Date: Sun, 02 Sep 2018 15:32:19 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH
Access-Control-Allow-Headers: X-CUSTOM-HEADER
Access-Control-Max-Age: 172800
X-Ca-Request-Id: 1016AC86-E345-405C-8049-A6C24078F65F
When you configure the API operation that allows only OPTIONS requests, note that API Gateway will add four header fields to each response from the backend service of the API operation: Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, and Access-Control-Max-Age. Therefore, you must add the four header fields as response header fields for the API operation and specify their values as needed, so that the custom values will override the default values.
The following code snippets show an example of a cross-origin API call in the preflighted request validation mode:
An OPTIONS request from a client
OPTIONS /simple HTTP/1.1
Host: www.alibaba.com
orgin: http://www.aliyun.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
accept: application/json; charset=utf-8
date: Mon, 18 Sep 2017 09:53:23 GMT
The response to the OPTIONS request, which is sent from the backend service of the API operation to API Gateway
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.aliyun.com
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: X-CUSTOM-HEADER
Access-Control-Max-Age: 10000
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
The response to the OPTIONS request, which is sent from API Gateway to the client
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.aliyun.com
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: X-CUSTOM-HEADER
Access-Control-Max-Age: 10000
X-Ca-Request-Id: 104735BD-8968-458F-9929-DBFA43F324C6
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
A cross-origin API request from the client
GET /simple HTTP/1.1
Host: www.alibaba.com
orgin: http://www.aliyun.com
content-type: application/x-www-form-urlencoded; charset=utf-8
accept: application/json; charset=utf-8
date: Mon, 18 Sep 2017 09:53:23 GMT
The response to the cross-origin request, which is sent from the backend service of the API operation to API Gateway
HTTP/1.1 200 OK
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}
The response to the cross-origin request, which is sent from API Gateway to the client
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH
Access-Control-Allow-Headers: X-Requested-With,X-Sequence,X-Ca-Key,X-Ca-Secret,X-Ca-Version,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-API-Key,X-Ca-Stage,X-Ca-Client-DeviceId,X-Ca-Client-AppId,X-Ca-Signature,X-Ca-Signature-Headers,X-Forwarded-For,X-Ca-Date,X-Ca-Request-Mode,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range,Content-MD5
Access-Control-Max-Age: 172800
X-Ca-Request-Id: 104735BD-8968-458F-9929-DBFA43F324C6
Date: Mon, 18 Sep 2017 09:53:23 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 12
{"200","OK"}