当我调用没有标题的服务器时,它的工作和服务器返回json:
this.http.get(url)
但是当我添加标题时:
var headers = new Headers({'x-id': '1'});
this.http.get(url, {'headers': headers})
浏览器返回错误:
XMLHttpRequest cannot load http://domain/api/v1/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
我还尝试添加Origin
标题 - 浏览器错误:Refused to set unsafe header "Origin"
Access-Control-Allow-Origin
标题 - 没效果
在服务器(Laravel)上,我创建了中间件Cors.php
:
<?php
namespace App\Http\Middleware;
use Closure;
class Cors {
public function handle($request, Closure $next)
{
return $next($request)
->header('Access-Control-Allow-Origin', 'http://localhost:3000')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'x-id');
}
}
我对angular2和CORS请求不熟悉,不知道该怎么做。
答案 0 :(得分:7)
使用CORS的预检请求意味着OPTIONS HTTP请求在实际请求之前执行。您从一个简单的请求切换到一个请求,因为您在GET方法的情况下添加自定义标头。此链接可以帮助您了解会发生什么:http://restlet.com/blog/2015/12/15/understanding-and-using-cors/。
仅供参考,执行跨域请求时,浏览器会自动添加Origin
标头。
我认为您的问题在Access-Control-Allow-Origin
标题内。您必须设置发出呼叫的主机,而不是服务器的地址。你应该这样做(如果你的Angular2应用程序在localhost:8080
上运行):
return $next($request)
->header('Access-Control-Allow-Origin', 'http://localhost:8080')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
->header('Access-Control-Allow-Headers', 'x-id');
希望它可以帮到你, 亨利
答案 1 :(得分:6)
我在Angular2应用程序中遇到了同样的问题。 如前所述,问题是在客户端发出每个请求之前,预检请求被发送到服务器。
此类请求的类型为 OPTIONS ,服务器有责任发回状态为200的预检响应,并设置标头以接受来自该客户端的请求
这是我的解决方案(快递):
// Domain you wish to allow
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'YOUR-CUSTOM-HEADERS-HERE');
// Set to true if you need the website to include cookies in requests
res.setHeader('Access-Control-Allow-Credentials', true);
// Check if Preflight Request
if (req.method === 'OPTIONS') {
res.status(200);
res.end();
}
else {
// Pass to next layer of middleware
next();
}
通过这种方式,客户端将获得授权,您可以在所有请求中设置自定义标头。在您的情况下,您必须在 Access-Control-Allow-Headers 选项中设置 x-id 。
答案 2 :(得分:1)
在您的情况下,服务器必须使用以下标题响应预检请求:
访问控制 - 允许 - 来源: *
X-Custom-HeaderAccess-Control-Allow-Methods: GET,POST,PUT,DELETE
访问控制允许标头:x-id
请注意,对于 Access-Control-Allow-Origin HTTP标头,最佳做法是设置明确托管angular2应用的域,而不是*,这对于您所在的公共API是必需的不要控制所有消费者!
我强烈建议您阅读以下关于CORS的文章:
答案 3 :(得分:1)
我一直在使用angular2
后端开发c# web api
应用,并遇到cors
设置问题。
真正的问题不是cors
设置,而是发送到api的数据(js日期对象到c#datetime类型没有正确排列)。但是,在您的情况下,是否必须在标头中传递x-id而不是作为请求的参数?例如,你可以做这样的事情:
getYourDataType(id: number): Observable<YourDataType> {
return this.http.get(url + '/' + id.toString())
.map((response: Response) => <YourDataType>response.json());
从处理这个问题后的研究来看,似乎angular
会试图找到你想要击中的端点,找不到它,然后假设原因必须是cors设置有问题,而不是客户端数据。
你说当你没有在你的请求上设置任何标题时,api会返回数据,所以如果从标题更改为参数不起作用,你可以尝试使用fiddler或网络等工具检查请求chrome的开发工具选项卡,看看每个请求的角度构造是否符合预期。或者通过在fiddler中手动构建请求来比较结果,可能会非常有启发性地说明为了给出这个意外响应而发生了什么。
无论如何,确定您的数据存在问题,而不是cors
设置非常困难。 Angular
你是否正在寻找一个完全错误的东西,试图找出一个非常简单的问题。我希望这有助于某人。
答案 4 :(得分:0)
问题是您还需要设置允许的标头。这就是为什么它无法正常工作的原因。要使其与简单的angular2 http请求一起使用,您需要添加以下标题:
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); // In your case also add x-id or what you are also using.
header('Access-Control-Allow-Methods: POST, PUT, DELETE, GET, OPTIONS');
答案 5 :(得分:0)
尝试以下代码,这应该有效
let headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
headers.append('x-id','1');
this.http.get(url, {'headers': headers}).subscribe(
response => {...},
error => {...}
);