CORS Post 请求失败
CORS Post Request Fails
我用 SLIM Micro-Framework 构建了一个 API。我使用以下代码设置了一些添加 CORS headers 的中间件。
class Cors{
public function __invoke(Request $request, Response $response, $next){
$response = $next($request, $response);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
}
对于我的 front-end,我使用了 VueJS。我设置了 VueResource 并使用以下代码创建了一个函数。
register (context, email, password) {
Vue.http({
url: 'api/auth/register',
method: 'POST',
data: {
email: email,
password: password
}
}).then(response => {
context.success = true
}, response => {
context.response = response.data
context.error = true
})
}
在 chrome 中,以下错误记录到控制台。
XMLHttpRequest cannot load http://mysite:9800/api/auth/register. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysite' is therefore not allowed access.
奇怪的是,GET 请求工作得很好。
发生这种情况是因为预检请求属于 OPTIONS 类型。您需要根据您的请求创建一个事件侦听器,它会检查类型并发送所需的响应 headers.
不幸的是我不知道 Slim 框架,但这是 Symfony 中的工作示例。
首先要返回的 headers 示例:
// Headers allowed to be returned.
const ALLOWED_HEADERS = ['Authorization', 'Origin', 'Content-Type', 'Content-Length', 'Accept'];
在请求侦听器中,有一个 onKernelRequest 方法可以监视所有传入的请求:
/**
* @param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
// Don't do anything if it's not the master request
if (!$event->isMasterRequest()) {
return;
}
// Catch all pre-request events
if ($event->getRequest()->isMethod('OPTIONS')) {
$router = $this->container->get('router');
$pathInfo = $event->getRequest()->getPathInfo();
$response = new Response();
$response->headers->set('Access-Control-Allow-Origin', $event->getRequest()->headers->get('Origin'));
$response->headers->set('Access-Control-Allow-Methods', $this->getAllowedMethods($router, $pathInfo));
$response->headers->set('Access-Control-Allow-Headers', implode(', ', self::ALLOWED_HEADERS));
$response->headers->set('Access-Control-Expose-Headers', implode(', ', self::ALLOWED_HEADERS));
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->headers->set('Access-Control-Max-Age', 60 * 60 * 24);
$response->send();
}
}
这里我只是重现了原点(所有域都可以请求资源,你应该把它改成你的域)。
希望能给点胶水
实际上,CORS 是在浏览器级别实现的。即使
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
chrome 并且 Mozilla 不会设置 headers 以允许跨源。所以,你需要强行禁用它..
阅读有关禁用 CORS 的更多信息
CORS 可能很难配置。关键是你需要在你的服务器和客户端中设置特殊的 headers,据我所知,我没有看到任何 Vue headers 设置 http
不是函数。但是,这里是 post 请求的一些设置。
const data = {
email: email,
password: password
}
const options = {
headers: {
'Access-Control-Expose-Headers': // all of your headers,
'Access-Control-Allow-Origin': '*'
}
}
Vue.http.post('api/auth/register', JSON.stringify(data), options).then(response => {
// success
}, response => {
// error
})
请注意,您需要对数据进行字符串化,并且需要公开您的 header,通常包括 Access-Control-Allow-Origin
header。
我在我自己的一个应用程序中所做的是定义拦截器,所以我不用担心为每个请求设置 headers。
Vue.http.headers.common['Access-Control-Expose-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, x-session-token, timeout, Content-Length, location, *'
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'
你一半 1/2 这里的解决方案。
您缺少的是一条 OPTIONS 路线,其中还需要添加这些 headers。
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
});
我用 SLIM Micro-Framework 构建了一个 API。我使用以下代码设置了一些添加 CORS headers 的中间件。
class Cors{
public function __invoke(Request $request, Response $response, $next){
$response = $next($request, $response);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
}
对于我的 front-end,我使用了 VueJS。我设置了 VueResource 并使用以下代码创建了一个函数。
register (context, email, password) {
Vue.http({
url: 'api/auth/register',
method: 'POST',
data: {
email: email,
password: password
}
}).then(response => {
context.success = true
}, response => {
context.response = response.data
context.error = true
})
}
在 chrome 中,以下错误记录到控制台。
XMLHttpRequest cannot load http://mysite:9800/api/auth/register. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mysite' is therefore not allowed access.
奇怪的是,GET 请求工作得很好。
发生这种情况是因为预检请求属于 OPTIONS 类型。您需要根据您的请求创建一个事件侦听器,它会检查类型并发送所需的响应 headers.
不幸的是我不知道 Slim 框架,但这是 Symfony 中的工作示例。
首先要返回的 headers 示例:
// Headers allowed to be returned.
const ALLOWED_HEADERS = ['Authorization', 'Origin', 'Content-Type', 'Content-Length', 'Accept'];
在请求侦听器中,有一个 onKernelRequest 方法可以监视所有传入的请求:
/**
* @param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event)
{
// Don't do anything if it's not the master request
if (!$event->isMasterRequest()) {
return;
}
// Catch all pre-request events
if ($event->getRequest()->isMethod('OPTIONS')) {
$router = $this->container->get('router');
$pathInfo = $event->getRequest()->getPathInfo();
$response = new Response();
$response->headers->set('Access-Control-Allow-Origin', $event->getRequest()->headers->get('Origin'));
$response->headers->set('Access-Control-Allow-Methods', $this->getAllowedMethods($router, $pathInfo));
$response->headers->set('Access-Control-Allow-Headers', implode(', ', self::ALLOWED_HEADERS));
$response->headers->set('Access-Control-Expose-Headers', implode(', ', self::ALLOWED_HEADERS));
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->headers->set('Access-Control-Max-Age', 60 * 60 * 24);
$response->send();
}
}
这里我只是重现了原点(所有域都可以请求资源,你应该把它改成你的域)。 希望能给点胶水
实际上,CORS 是在浏览器级别实现的。即使
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
chrome 并且 Mozilla 不会设置 headers 以允许跨源。所以,你需要强行禁用它..
阅读有关禁用 CORS 的更多信息
CORS 可能很难配置。关键是你需要在你的服务器和客户端中设置特殊的 headers,据我所知,我没有看到任何 Vue headers 设置 http
不是函数。但是,这里是 post 请求的一些设置。
const data = {
email: email,
password: password
}
const options = {
headers: {
'Access-Control-Expose-Headers': // all of your headers,
'Access-Control-Allow-Origin': '*'
}
}
Vue.http.post('api/auth/register', JSON.stringify(data), options).then(response => {
// success
}, response => {
// error
})
请注意,您需要对数据进行字符串化,并且需要公开您的 header,通常包括 Access-Control-Allow-Origin
header。
我在我自己的一个应用程序中所做的是定义拦截器,所以我不用担心为每个请求设置 headers。
Vue.http.headers.common['Access-Control-Expose-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, x-session-token, timeout, Content-Length, location, *'
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'
你一半 1/2 这里的解决方案。
您缺少的是一条 OPTIONS 路线,其中还需要添加这些 headers。
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response
->withHeader('Access-Control-Allow-Origin', 'http://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
});