Post 请求在 Postman 中工作,但 returns 预检错误在 Angular 2 应用程序中
Post Request working in Postman but returns Preflight error in Angular 2 app
这是来自浏览器控制台的错误日志
XMLHttpRequest 无法加载 http://domain.com/xx/xxxxxxxx。预检响应具有无效的 HTTP 状态代码 404
这是在 Postman 中收到的预期响应
{
"status": "success",
"code": "E012",
"message": "Contact sent"
}
这是 Angular 2
提出的要求
makeRequest(name, recipient) {
let body = JSON.stringify({
"name": name,
"recipient": recipient
});
let authToken = localStorage.getItem('token');
console.log(authToken);
let headers = new Headers({'Authorization': authToken , 'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.post(url, body, options )
.map(res => res.json());
}
这里是 Yii2 中的 behaviors 函数
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// 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' => [],
],
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
这是我的 UrlManager
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
'POST <version:[\w-]+>/sms' => '<version>/sms/send',
'POST <version:[\w-]+>/users/verify' => '<version>/user/verify',
'POST <version:[\w-]+>/bulk' => '<version>/routine/index',
'POST <version:[\w-]+>/contact' => '<version>/contact/index'],
你应该在没有 JSON.stringify
的情况下发送正文:
let body = {
"name": name,
"recipient": recipient
};
祝你好运
在某些情况下,浏览器会在实际发送卷轴之前自动执行 preflight request 检查允许的方法或动词列表。您可以在浏览器的网络选项卡中看到这些内容。我想在 Postman 中你是直接发送 POST
请求,而 pre-sent OPTIONS
请求应该是失败的请求。
Yii 有一个 built-in action which is defined under the ActiveController class 来响应这样的请求。但是在您的情况下,您直接扩展了它的父控制器,因此您需要在控制器中手动定义类似的操作 (或它们的父控制器) 以响应预检请求:
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));
}
还有;因为你没有使用 built-in routing mechanism for REST;在您的情况下,您还需要手动定义 rules
到 Options 操作:(根据您的评论编辑的代码版本)
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
'POST <version:[\w-]+>/users/verify' => '<version>/user/verify',
'POST <version:[\w-]+>/airtime' => '<version>/airtime/airtime',
'POST <version:[\w-]+>/bulk' => '<version>/routine/index',
'POST <version:[\w-]+>/contact' => '<version>/contact/index',
// OPTTIONS URI ENDPOINTS
'OPTIONS <version:[\w-]+>/users/verify' => '<version>/user/options',
'OPTIONS <version:[\w-]+>/airtime' => '<version>/airtime/options',
'OPTIONS <version:[\w-]+>/bulk' => '<version>/routine/options',
'OPTIONS <version:[\w-]+>/contact' => '<version>/contact/options',
],
];
这是来自浏览器控制台的错误日志 XMLHttpRequest 无法加载 http://domain.com/xx/xxxxxxxx。预检响应具有无效的 HTTP 状态代码 404
这是在 Postman 中收到的预期响应
{
"status": "success",
"code": "E012",
"message": "Contact sent"
}
这是 Angular 2
提出的要求makeRequest(name, recipient) {
let body = JSON.stringify({
"name": name,
"recipient": recipient
});
let authToken = localStorage.getItem('token');
console.log(authToken);
let headers = new Headers({'Authorization': authToken , 'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http.post(url, body, options )
.map(res => res.json());
}
这里是 Yii2 中的 behaviors 函数
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// 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' => [],
],
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
这是我的 UrlManager
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
'POST <version:[\w-]+>/sms' => '<version>/sms/send',
'POST <version:[\w-]+>/users/verify' => '<version>/user/verify',
'POST <version:[\w-]+>/bulk' => '<version>/routine/index',
'POST <version:[\w-]+>/contact' => '<version>/contact/index'],
你应该在没有 JSON.stringify
的情况下发送正文:
let body = {
"name": name,
"recipient": recipient
};
祝你好运
在某些情况下,浏览器会在实际发送卷轴之前自动执行 preflight request 检查允许的方法或动词列表。您可以在浏览器的网络选项卡中看到这些内容。我想在 Postman 中你是直接发送 POST
请求,而 pre-sent OPTIONS
请求应该是失败的请求。
Yii 有一个 built-in action which is defined under the ActiveController class 来响应这样的请求。但是在您的情况下,您直接扩展了它的父控制器,因此您需要在控制器中手动定义类似的操作 (或它们的父控制器) 以响应预检请求:
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));
}
还有;因为你没有使用 built-in routing mechanism for REST;在您的情况下,您还需要手动定义 rules
到 Options 操作:(根据您的评论编辑的代码版本)
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
'POST <version:[\w-]+>/users/verify' => '<version>/user/verify',
'POST <version:[\w-]+>/airtime' => '<version>/airtime/airtime',
'POST <version:[\w-]+>/bulk' => '<version>/routine/index',
'POST <version:[\w-]+>/contact' => '<version>/contact/index',
// OPTTIONS URI ENDPOINTS
'OPTIONS <version:[\w-]+>/users/verify' => '<version>/user/options',
'OPTIONS <version:[\w-]+>/airtime' => '<version>/airtime/options',
'OPTIONS <version:[\w-]+>/bulk' => '<version>/routine/options',
'OPTIONS <version:[\w-]+>/contact' => '<version>/contact/options',
],
];