
# 跨域调用APIC开放的API
出于安全性考虑，浏览器会限制从页面脚本内发起的跨域请求，此时页面只能访问当前域的资源。CORS允许浏览器向跨域服务器发送XMLHttpRequest请求，从而实现跨域访问。
图1跨域访问   
![](https://support.huaweicloud.com/usermanual-roma/zh-cn_image_0000001282715612.png)
浏览器将CORS请求分为两类：简单请求和非简单请求。
- **简单请求** ：同时满足以下2个条件的，即为简单请求。
  - 请求方法为HEAD/GET/POST。
  
  - HTTP的头信息不超出以下几种字段：Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type（只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain）。
  
  
  对于简单请求，浏览器自动在头信息之中添加一个Origin字段，用于说明本次请求来自哪个源（协议+域名+端口）。服务器根据Origin字段，决定是否同意这次请求。服务器响应消息中包含"Access-Control-Allow-Origin"时，表示同意请求。
  
- **非简单请求** ：不满足以上2个条件的，都为非简单请求。
  对于非简单请求，在正式通信之前，浏览器会增加一次HTTP查询请求，称为预检请求。浏览器查询服务器，当前页面所在的源是否在服务器的许可名单之中，以及可以使用哪些HTTP请求方法和头信息字段。预检通过后，浏览器向服务器发送简单请求。
  
ROMA Connect默认不支持跨域访问，如果您需要支持跨域访问，则需要在[创建API](https://support.huaweicloud.com/usermanual-roma/roma_03_2105.html)时打开"支持CORS"功能。CORS为非简单请求时，还需要创建一个"Method"为"OPTIONS"的API作为预检请求。
#### 简单请求
- **场景一：** 已开启CORS，且后端服务响应消息中未指定跨域头时，ROMA Connect接受任意域的请求，并返回"Access-Control-Allow-Origin"跨域头，示例如下。
  1. **浏览器发送一个带Origin字段的请求消息。**
     ```
     GET /simple HTTP/1.1
     Host: www.test.com
     Origin: http://www.cors.com
     Content-Type: application/x-www-form-urlencoded; charset=utf-8
     Accept: application/json
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     ```
     Origin：必选字段，表示请求消息所属源，上例中请求来源于"http://www.cors.com"，ROMA Connect和后端服务根据这个值，决定是否同意本次请求。
     
  
  2. **后端服务返回响应消息。**
     ```
     HTTP/1.1 200 OK
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     Content-Type: application/json
     Content-Length: 16
     Server: roma
     {"status":"200"}
     ```
     
  
  3. **ROMA Connect返回响应消息。**
     ```
     HTTP/1.1 200 OK
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     Content-Type: application/json
     Content-Length: 16
     Server: roma
     X-Request-Id: 454d689fa69847610b3ca486458fb08b
     Access-Control-Allow-Origin: *
     {"status":"200"}
     ```
     Access-Control-Allow-Origin：必选字段，"\*"表示ROMA Connect接受任意域的请求。
     
   
- **场景二：** 已开启CORS，且后端服务响应消息中指定跨域头时，后端服务响应的跨域头将覆盖ROMA Connect增加的跨域头，示例如下。
  1. **浏览器发送一个带Origin字段的请求消息。**
     ```
     GET /simple HTTP/1.1
     Host: www.test.com
     Origin: http://www.cors.com
     Content-Type: application/x-www-form-urlencoded; charset=utf-8
     Accept: application/json
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     ```
     Origin：必选字段，表示请求消息所属源，上例中请求来源于"http://www.cors.com"，ROMA Connect和后端服务根据这个值，决定是否同意本次请求。
     
  
  2. **后端服务返回响应消息。**
     ```
     HTTP/1.1 200 OK
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     Content-Type: application/json
     Content-Length: 16
     Server: roma
     Access-Control-Allow-Origin: http://www.cors.com
     {"status":"200"}
     ```
     Access-Control-Allow-Origin：表示后端服务接受"http://www.cors.com"的请求。
     
  
  3. **ROMA Connect返回响应消息。**
     ```
     HTTP/1.1 200 OK
     Date: Tue, 15 Jan 2019 01:25:52 GMT
     Content-Type: application/json
     Content-Length: 16
     Server: roma
     X-Request-Id: 454d689fa69847610b3ca486458fb08b
     Access-Control-Allow-Origin: http://www.cors.com
     {"status":"200"}
     ```
     后端服务响应消息中的跨域头覆盖ROMA Connect响应消息中的跨域头。
     
   
 
#### 非简单请求
对于非简单请求，您还需要创建一个"Method"为"OPTIONS"的API。"Method"为"OPTIONS"的API和普通API的区别如下：
- 所属分组：选择与已开启CORS的API相同的API分组。
- 安全认证：无论选择哪种认证方式，APIC都按照无认证处理。
- 请求协议：选择与已开启CORS的API相同的请求协议。
- 请求Path：选择与已开启CORS的API相同或匹配的请求Path。
- Method：选择"OPTIONS"。
- 支持CORS：选择开启CORS。
- 后端服务：后端服务响应为200 OK。
假设后端服务类型为Mock，示例如下。
1. **浏览器发送"Method"为"OPTIONS"的API请求。**
   ```
   OPTIONS /HTTP/1.1
   User-Agent: curl/7.29.0
   Host: localhost
   Accept: */*
   Origin: http://www.cors.com
   Access-Control-Request-Method: PUT 
   Access-Control-Request-Headers: X-Sdk-Date
   ```
   - Origin：必选字段，表示请求消息所属源。
   
   - Access-Control-Request-Method：必选字段，表示请求会使用的HTTP请求方法。
   
   - Access-Control-Request-Headers：必选字段，表示请求会额外发送的头信息字段。
    
2. **后端服务返回响应消息。**
   无
   
3. **ROMA Connect返回响应消息。**
   ```
   HTTP/1.1 200 OK
   Date: Tue, 15 Jan 2019 02:38:48 GMT
   Content-Type: application/json
   Content-Length: 1036
   Server: roma
   X-Request-Id: c9b8926888c356d6a9581c5c10bb4d11
   Access-Control-Allow-Origin: *
   Access-Control-Allow-Headers: X-Stage,X-Sdk-Date,X-Sdk-Nonce,X-Proxy-Signed-Headers,X-Sdk-Content-Sha256,X-Forwarded-For,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range
   Access-Control-Expose-Headers: X-Request-Id,X-Apig-Latency,X-Apig-Upstream-Latency,X-Apig-RateLimit-Api,X-Apig-RateLimit-User,X-Apig-RateLimit-App,X-Apig-RateLimit-Ip,X-Apig-RateLimit-Api-Allenv
   Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH
   Access-Control-Max-Age: 172800
   ```
   - Access-Control-Allow-Origin：必选字段，"\*"表示ROMA Connect接受任意域的请求。
   
   - Access-Control-Allow-Headers：当请求消息中包含此字段时，此字段必选。表示ROMA Connect支持的头信息字段。
   
   - Access-Control-Allow-Methods：必选字段，表示ROMA Connect支持的HTTP请求方法。
   
   - Access-Control-Max-Age：必选字段，表示本次预检的有效期，单位：秒。在有效期内，无需再次发送预检请求。
    
4. **浏览器发送一个带Origin字段的请求消息。**
   ```
   PUT /simple HTTP/1.1
   Host: www.test.com
   Origin: http://www.cors.com
   Content-Type: application/x-www-form-urlencoded; charset=utf-8
   Accept: application/json
   Date: Tue, 15 Jan 2019 01:25:52 GMT
   ```
   Origin：必选字段，表示请求消息所属源。
   
5. **后端服务返回响应消息。**
   ```
   HTTP/1.1 200 OK
   Date: Tue, 15 Jan 2019 01:25:52 GMT
   Content-Type: application/json
   Content-Length: 16
   Server: roma
   {"status":"200"}
   ```
   
6. **APIC返回响应消息。**
   ```
   HTTP/1.1 200 OK
   Date: Tue, 15 Jan 2019 01:25:52 GMT
   Content-Type: application/json
   Content-Length: 16
   Server: roma
   X-Request-Id: 454d689fa69847610b3ca486458fb08b
   Access-Control-Allow-Origin: *
   {"status":"200"}
   ```
   
 
