angular2 和 Yii2 应用程序中的预检错误

Posted

技术标签:

【中文标题】angular2 和 Yii2 应用程序中的预检错误【英文标题】:Preflight error in angular2 and Yii2 application 【发布时间】:2017-05-27 21:50:38 【问题描述】:

我在调用端点时遇到了 CORS 错误,请参阅下面的错误:

XMLHttpRequest 无法加载 http://domain.com/v1/airtime。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://domain.com' 不允许访问。响应的 HTTP 状态代码为 404。

我在 API 根文件夹的 .htaccess 文件中添加了 Header set Access-Control-Allow-Origin "*"。错误消失并替换为以下错误:

XMLHttpRequest 无法加载 domain/v1/airtime。预检响应包含无效的 HTTP 状态代码 404

我寻求的所有其他解决方案都无法解决该问题。如何处理预检错误?

下面是我用来在 BaseController 中解决 CORS 的代码,但似乎还不够,我仍然收到预检错误。

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => Cors::className(),
        'cors' => [
            // restrict access to
            'Origin' => ['*'],
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            // Allow only POST and PUT methods
            'Access-Control-Request-Headers' => ['*'],
            // Allow only headers 'X-Wsse'
            'Access-Control-Allow-Credentials' => true,
            // Allow OPTIONS caching
            'Access-Control-Max-Age' => 86400,
            // Allow the X-Pagination-Current-Page header to be exposed to the browser.
            'Access-Control-Expose-Headers' => [],
    ];`

我的 proxy.conf.json 文件内容如下:

"/api": "target": "http://domain.com/v1", "secure": false, "pathRewrite" : "^api" : ""

【问题讨论】:

在您的服务器端 (yii) 将标头 Access-Control-Allow-Origin 设置为 *,或者在您的 angular2 应用程序中使用 代理。 ***.com/questions/36002493/… 我在 yii 中设置了标题 Access-Control-Allow-Origin "*",如我的问题中所述。代理似乎也不起作用,因为我仍然收到 404。 您确定您使用正确的端口指向正确的 URL 吗? 404 是找不到页面或找不到资源。你能在angular2中发布你的代理配置吗? 我已将我的 proxy.conf.json 内容添加到问题中。 如果我用邮递员测试它可以工作,但它不能在浏览器上工作。 API 托管在 EC2 Ubuntu 实例上。 【参考方案1】:

找不到 404 页面或资源。资源存在吗?你得到请求的 URL 和方法了吗?

您是否允许使用预检 OPTIONS 方法?确保这是允许的 CORS 方法。

当您在 Angular2 之外请求该 URL 时,它是否有效(例如,在邮递员中使用 GET / POST)?如果不是,请先解决该问题。

【讨论】:

我允许 preflight OPTIONS 方法和 GET / POST 在邮递员中工作。 好吧,听起来你已经接近了,你能检查一下邮递员中的响应头吗,你在响应头中看到你的 CORS(访问)头吗? 请参阅下面的响应标头中的内容:Access-Control-Allow-Credentials →true Access-Control-Allow-Origin →* Access-Control-Expose-Headers → Connection →close Content-Length →65 Content-Type →application/json; charset=UTF-8 Date →Fri, 13 Jan 2017 12:05:38 GMT Server →Apache/2.4.18 (Ubuntu) 我在其中看不到 Access-Control-Request-Method 但它在您的代码中? 是的,它在我的代码中。 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],【参考方案2】:

我假设你也有同样的问题:

在某些情况下,浏览器会在实际发送卷轴之前自动执行预检请求以检查允许的方法或动词列表。您可以在浏览器的网络选项卡中看到这些内容。我猜在 Postman 中您是直接发送 POST 请求,而当前发送的 OPTIONS 请求应该是失败的请求。

Yii 有一个在 ActiveController 类下定义的内置动作来响应这些请求。但是在您的情况下,您是直接扩展其父控制器,因此您需要在控制器(或它们的父控制器)内手动定义类似的操作,以响应预检请求:

将此添加到您的基本控制器

public function actionOptions() 

if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') 
    Yii::$app->getResponse()->setStatusCode(405);


$allowed_verbs = ['GET', 'POST', 'HEAD', 'OPTIONS'];
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed_verbs));

还有;因为您没有使用 REST 的内置路由机制;在您的情况下,您还需要手动定义该选项操作的规则:(来自您的 cmets 的代码的编辑版本)

'urlManager' => [ 
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [ 
    'POST <version:[\w-]+>/users/verify' => '<version>/user',

    // OPTTIONS URI ENDPOINTS
    'OPTIONS <version:[\w-]+>/users/verify' => '<version>/user',
],
];

【讨论】:

以上是关于angular2 和 Yii2 应用程序中的预检错误的主要内容,如果未能解决你的问题,请参考以下文章

在yii2中的会话工作地点

JS中的预编译(词法分析)阶段和执行阶段

最小码距和检错纠错能力关系

计算机网络-数据链路层差错控制(检错编码纠错编码)

计算机网络-数据链路层差错控制(检错编码纠错编码)

Angularjs:Cloudinary 上传小部件中的预填充搜索字段