CORS问题,Chrome浏览器上的飞行前请求

时间:2019-03-19 21:32:14

标签: php symfony ionic-framework cors

我正在开发的应用程序有问题。 该API位于PHP Symfony 4中,该应用程序由Ionic 4组成。

执行PATCH请求时遇到问题。该请求在POSTMAN以及我的手机上都可以很好地工作 但是在尝试使用浏览器(Google Chrome,Firefox)时,CORS出现问题。

我已经查询,并且我已经了解到PATCH请求首先经过飞行前请求,因此发送了一个请求 使用我的API的OPTIONS方法。

我管理了此方法并返回了代码200,然后按如下所示在index.php文件中允许了正确的标头:

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header("Access-Control-Allow-Methods: GET, HEAD, PATCH, OPTIONS, POST, PUT");

一开始,我遇到了第一个错误,该错误指示该请求未返回代码200,因此我在自己的API中管理了OPTIONS方法。 然后出现以下错误:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

这很奇怪,因为之前没有出现该错误,其他所有请求都可以正常工作。

此外,我尝试使用POSTMAN,并且OPTIONS方法返回正确的标头。

你能帮我吗?

对不起,英语很粗糙。

2 个答案:

答案 0 :(得分:1)

对于将来发现此问题的任何人,我都重现了这些确切的症状,并解决了我的问题。简短的回答是,当在客户端指定方法时(例如在 fetch 选项中),PATCH 特别区分大小写,而其他方法则不区分。它需要大写。

尽我所能推断出的解释是,即使 RFC7230 声明方法应该大写,但它们也区分大小写。浏览器通过自动将其中几个大写来解决这个问题,我相信基于 RFC7231 定义了许多常用方法,但没有定义 PATCH。考虑以下从客户端发起的请求。

fetch('https://stackoverflow.com', 
  { method: 'post', 
    body: JSON.stringify({message: 'testing a cors issue'}), 
    headers:  {'Content-Type': 'application/json'}
  }
)

至少 Chromium 浏览器的正常行为是自动将 CORS 预检的 Access-Control-Request-Method 标头中的方法大写,而不管我的 JavaScript 在 fetch 调用中使用的大写。

Preflight request with capitalized post method

同样,如果方法是 DELETE,浏览器也会在预检中自动将其大写。

但是,我发现 PATCH 方法(稍后在 RFC5789 中定义)被视为自定义 HTTP 方法,因为它没有强制大写。因此,它区分大小写,这在 CORS 预检期间可以观察到。如果客户端应用程序以小写 patch 指定它,它就是它在 Access-Control-Request-Method 标头中的显示方式,如果它是大写的 PATCH,它在标头中显示为大写。

Preflight showing lowercase patch method

当您在 Postman 中选择 PATCH 方法时,它总是大写,这掩盖了问题的根本原因。尽管错误消息与 Access-Control-Allow-Origin 标头有关,但我看到的根本原因是该方法区分大小写。

答案 1 :(得分:0)

Environement info-
   ionic (Ionic CLI)             : 4.0.0 
   Ionic Framework               : @ionic/angular 4.0.0
   @angular-devkit/build-angular : 0.8.6
   @angular-devkit/schematics    : 0.8.6
   @angular/cli                  : 6.2.6
   @ionic/angular-toolkit        : 1.1.0

要解决 CORS 错误,您应该按照以下步骤操作:

  1. 创建到您的Ionic项目中(在根目录中),文件名为: proxy.conf.json 在里面写上(复制/粘贴):
"/api/*": {  
    "target": "http://myremoteserver/api",  
    "secure": false,  
    "logLevel": "debug"  
}
  1. 打开您的angular.json文件,并将行proxyConfig": "proxy.conf.json"设置为如下所示的 “ serve”

    "serve": {
              "builder": "@angular-devkit/build-angular:dev-server",
              "options": {
                "browserTarget": "app:build",
                proxyConfig": "proxy.conf.json"
              },
              "configurations": {
                "production": {
                  "browserTarget": "app:build:production"
    
  2. 打开您的package.json并将此行添加到 脚本 数组:

    "start": "ng serve --port 8100 --proxy-config proxy.conf.json" 
    

    您应得的东西是这样的(见下文):

    "scripts": {
        "ng": "ng",
        "start": "ng serve --port 8100 --proxy-config proxy.conf.json",
        "build": "ng build",
        "test": "ng test",
        "lint": "ng lint",
        "e2e": "ng e2e"
      }
    
  3. 在命令行中运行以下命令:npm run start

如果您按照此步骤操作,应该确定

  

就我而言,它正在工作!!!

最诚挚的问候