Angular 2 应用程序到 Rails 5 后端的 CORS 问题

Posted

技术标签:

【中文标题】Angular 2 应用程序到 Rails 5 后端的 CORS 问题【英文标题】:CORS issue on Angular2 app to Rails5 Back-end 【发布时间】:2017-07-24 23:19:42 【问题描述】:

从我记事起,我就一直在与 CORS 作斗争,但我正在尝试一件非常简单的事情:C9 上的 3 个微服务 - 所有 3 个差异端口,因此来源不同。

在 Rails 中:

Program A-cors.rb-不起作用

Rails.application.config.middleware.insert_before 0, Rack::Cors do
    allow do
     origins '*'

     resource '*',
       headers: :any,
       methods: [:get, :post, :put, :patch, :delete, :options, :head]
    end
end

Program B - cors.rb有效

Rails.application.config.middleware.insert_before 0, Rack::Cors do
    allow do
     origins '*'

     resource '*',
       headers: :any,
       methods: [:get, :post, :put, :patch, :delete, :options, :head]
    end
end

Angular2 服务也非常相似(只是名称改变)所以我只显示

Program As - service

import  Injectable  from '@angular/core'
import  Http, Response, Headers, RequestOptions  from '@angular/http';
import  Observable  from 'rxjs/Rx';

import  Document  from './document';

@Injectable()
export class DocumentService
    private documentsUrl = "//freeland-camp-documents-dnorthrup.c9users.io/freelance_documents.json";

    constructor(
        private http: Http    
    ) 

    getDocuments(): Observable<Document[]> 
        let headers = new Headers( 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' );
        let options = new RequestOptions( headers: headers );
        return this.http.get(this.documentsUrl)
                        .map((response: Response) => <Document[]>response.json())
                        .catch(this.handleError);
    

    private handleError (error: Response | any) 
        // In a real world app, we might use a remote logging infrastructure
        let errMsg: string;
        if (error instanceof Response) 
          const body = error.json() || '';
          const err = body.error || JSON.stringify(body);
          errMsg = `$error.status - $error.statusText || '' $err`;
         else 
          errMsg = error.message ? error.message : error.toString();
        
        console.error(errMsg);
        return Observable.throw(errMsg);
    

let headers 是我在阅读另一篇文章后尝试做出的最新更改。根据我对 CORS 的了解,Rails 禁止这样做,但是,每次从 Angular 进行调用时,我都会看到

Started GET "/freelance_documents.json" for 108.51.108.71 at 2017-03-04 23:46:38 +0000
Processing by FreelanceDocumentsController#index as JSON
  FreelanceDocument Load (0.5ms)  SELECT "freelance_documents".* FROM "freelance_documents" ORDER BY created_at DESC
Completed 200 OK in 8ms (Views: 6.5ms | ActiveRecord: 0.5ms)

在控制台中 - 好像 Rails 认为它​​成功发生了(我认为这是因为 Rails 处于 API 模式并且 JSON 总是呈现?

我到底错过了什么?程序 B 最初在那里有真正的原始 URL 并且仍然有效,将其更改为 * 并没有解决任何问题。

根据我发现的 Rails5 文章,我还放置了:

config.action_dispatch.default_headers = 
  'Access-Control-Allow-Origin' => 'freeland-camp-documents-dnorthrup.c9users.io:8082',
  'Access-Control-Request-Method' => %wGET POST OPTIONS.join(",")

在 Application.rb 中无济于事。欢迎任何见解 - 我没有想法。我尝试使用 Chrome 的插件绕过标头(无效)并导致Program A 工作但打破Program B 说“origin evil.com 不够”。 - 这是我没有*的时候。

欢迎任何意见。

【问题讨论】:

【参考方案1】:

对于遇到这种情况的人:

我能够通过修改解决我的问题 config/application.rb 包括:

config.action_dispatch.default_headers = 
  'Access-Control-Allow-Origin' => '*',
  'Access-Control-Request-Method' => %wGET POST OPTIONS.join(",")

是正确的解决方案 - 似乎我遇到了一些缓存问题。 我没有使用 * 表示 Origin,而是调用它的确切域。

最后我需要cors.rb 两者都有:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
    allow do
     origins '*'

     resource '*',
       headers: :any,
       methods: [:get, :post, :put, :patch, :delete, :options, :head]
    end
end

application.rb 拥有

config.action_dispatch.default_headers = 
  'Access-Control-Allow-Origin' => '*',
  'Access-Control-Request-Method' => %wGET POST OPTIONS.join(",")

【讨论】:

以上是关于Angular 2 应用程序到 Rails 5 后端的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

Rails 的 Angular 2 CSRF 令牌

将 Angular 2 应用程序部署到 Heroku

升级到 Rails 4.2.5.1 后 nil:NilClass 的未定义方法“缓存”

将 Rails 5.2 升级到 6.0.0 后内存泄漏

Angular/Ionic/Phonegap 应用程序与 Rails API Web 服务 Auth

从 ruby​​ on rails 重定向到 angular 给 preflight 的响应是无效错误