Angular2标头

时间:2015-12-21 21:29:26

标签: laravel cors angular

当我调用没有标题的服务器时,它的工作和服务器返回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请求不熟悉,不知道该怎么做。

  • Angular:2.0.0-beta.0
  • Laravel:5.0
  • 浏览器:Google Chrome

6 个答案:

答案 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的文章:

http://www.html5rocks.com/en/tutorials/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 => {...}
);