46

Rails 4 を使用して一連のサービスを作成しています。これは、JavaScript ブラウザー アプリケーションで使用しています。クロスオリジン GETS は正常に動作していますが、私の POST は 404 エラーでプリフライト OPTIONS チェックに失敗しています。少なくとも、私はそれが起こっていると思います。コンソールに表示されるエラーは次のとおりです。これは Mac 上の Chrome 31.0.1650.63 です。

OPTIONS http://localhost:3000/confessor_requests 404 (Not Found) jquery-1.10.2.js:8706
OPTIONS http://localhost:3000/confessor_requests No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. jquery-1.10.2.js:8706
XMLHttpRequest cannot load http://localhost:3000/confessor_requests. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. main.html:1

CORS を有効にするための手順を高低で検索しましたが、困惑しています。通常の推奨事項は、私が行ったアプリケーションコントローラーにこのようなものを配置することです。

before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers

def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*'
  headers['Access-Control-Max-Age'] = "1728000"
end

def cors_preflight_check
  if request.method == :options
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, PUT, GET, OPTIONS'
    headers['Access-Control-Allow-Headers'] = '*'
    headers['Access-Control-Max-Age'] = '1728000'
    render :text => '', :content_type => 'text/plain'
  end
end

OPTIONS リクエストが入ったときにこのアクションにリダイレクトする、routes.rb のある種のルートが続きます。

match "/*all" => "application#cors_preflight_check", :constraints => { :method => "OPTIONS" }

'match' ディレクティブは Rails 4 では機能しなくなったので、次のように POSTS と直接一致させようと試みました。

post "/*all" => "application#cors_preflight_check", :constraints => { :method => :options }

しかし、それでもうまくいきません。GET リクエストが機能しているので、私が見逃しているのは OPTIONS リクエストの正しいルートだと思います。ただし、考えられるすべてのルートを試しましたが、リクエストを通過させるものは何もないようです。

cyu/rack-corsもインストールしてみましたが、同じ結果が得られました。

私が間違っていることを知っている人はいますか?

4

8 に答える 8

7

はい、他の人が指摘しているように、おそらくこれをより適切に行うGEMがあります。しかし、元のブログ投稿で指摘された cors コードの方法が非常に気に入ったので、そのコードを使用している場合は、 Rails 4ソリューションを見つけました。

あなたの routes.rb で:

match '*all' => 'my_method_name#cor', via: :options

my_method_name コントローラーで:

def cor
    # blank section for CORR
    render :text => ''
end

それに加えて他のコードがある限り:

before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
...

次に、Rails 4 の設定を行う必要があります。

于 2015-05-06T04:28:38.120 に答える
4

おそらく、この要点が役に立ちます: CORS in Rails 4 APIs

メソッドをルート定義に追加OPTIONSし、API ベース コントローラーにフィルターを追加して、正しいヘッダーでリクエストに直接応答しOPTIONS、他のすべてのアクションにも正しい CORS ヘッダーを設定します。

于 2014-07-10T09:21:27.787 に答える
2

私は同じ問題に遭遇し、現在、考えられるセキュリティ/パフォーマンスの問題について次のルートを評価しています。彼らは問題を解決しますが...

match '/', via: [:options], 
 to:  lambda {|env| [200, {'Content-Type' => 'text/plain'}, ["OK\n"]]}
match '*unmatched', via: [:options],  
 to:  lambda {|env| [200, {'Content-Type' => 'text/plain'}, ["OK\n"]]}

「match」は Rails 4 では機能しないと思われますが、特定のメソッドに制限すると機能するようです。

于 2014-11-27T04:00:46.310 に答える
1

Rails 4 APIに接続するためにクライアント側で何をしているのかについて詳しく説明していないため、どのJavaScriptフロントエンドフレームワークを使用しているか(または使用している場合)はわかりませんが、追加すると思いましたそれが誰かを助ける場合の私の答え。

AngularJS フロントエンドから Devise gem を使用して Rails 4 API に接続しているときに、まったく同じ問題に遭遇しました (どちらも別々の localhost ポートで実行されていました)。AngularJS フォームから POST リクエストを使用してバックエンドにログインしようとしましたが、プリフライトで OPTIONS リクエストを送信していたため、404 NOT FOUND エラーが発生し続けました。問題を解決する方法を見つけるのに 2 日以上かかりました。

基本的に、API に接続するために、フロント エンド (Angular、Backbone など) 用のプロキシ サーバーをセットアップして、フロント エンドがリクエストが同じオリジンを使用していると見なす必要があります。GruntJS を使用してプロキシを設定するための簡単なソリューションがいくつかあります。Gulp-Connect とプロキシ ミドルウェアを使用してプロジェクトに Gulp を使用し、次のセットアップを行います (ここにあるソリューションに基づく)。

var gulp            = require('gulp'),
    connect         = require('gulp-connect');

gulp.task('devServer', function() {
      connect.server({
        root: './dist',
        fallback: './dist/index.html',
        port: 5000,
        livereload: true,
        middleware: function(connect, o) {
            return [ (function() {
                var url = require('url');
                var proxy = require('proxy-middleware');
                var options = url.parse('http://localhost:3000/');
                options.route = '/api';
                return proxy(options);
            })() ];
        }
      });
    });

これが誰かに役立つことを願っています!

于 2014-08-01T23:24:06.230 に答える