Angular フロントエンドと Rails バックエンド API を完全に統合できません。どちらも異なるサーバーで実行されているため、CORS に問題があると思います。
私の Angular アプリは、クエリ (GET) および保存 (POST) メソッドを持つリソースを持つサービスを呼び出すコントローラーを実行しています。クエリ (GET) は正常に動作していますが、投稿は動作していません。
パラメータを送信しない場合でも、サーバーに POST リクエストを送信できます。次のようになります。
コントローラ:
$scope.createBusiness = function() {
console.log("Business.name=" + $scope.business.name);
$scope.business = Business.save();
};
サービス:
.factory('Business',
function($resource){
var businesses =
$resource('http://127.0.0.1\\:3000/:business', {business:'businesses'}, {
query: {method:'GET', isArray: true},
save: {method:'POST', isArray: false}
});
return businesses;
}
);
ただし、モデル パラメータを投稿したいので、何かを送信しようとすると、POST リクエストではなく OPTIONS リクエストを送信します。すると、エラーが発生します。
リクエストを送信するときにリクエストデータを確認してくださいそれなしパラメータ(POSTリクエスト):
Request URL:http://127.0.0.1:3000/businesses
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:es-ES,es;q=0.8
Connection:keep-alive
Content-Length:0
Content-Type:text/plain;charset=UTF-8
Host:127.0.0.1:3000
Origin:http://localhost:1234
Referer:http://localhost:1234/app/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
Response Headersview source
Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization
Access-Control-Allow-Methods:POST, PUT, DELETE, GET, OPTIONS
Access-Control-Allow-Origin:*
Access-Control-Max-Age:1728000
Access-Control-Request-Method:*
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:9
Content-Type:application/json; charset=utf-8
Date:Mon, 04 Nov 2013 16:50:33 GMT
Etag:"ccd3d779b6f97e2c24633184cbc8f98c"
Server:WEBrick/1.3.1 (Ruby/2.0.0/2013-06-27)
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-Id:e084295e-c7c6-4566-80d1-6e2a8ac2e712
X-Runtime:0.034000
X-Ua-Compatible:chrome=1
X-Xss-Protection:1; mode=block
サーバーにアクセスし、メソッドを実行して応答を取得します。これで問題ありません。
リクエストを送信したときにリクエストデータを確認するとパラメータ(OPTIONSリクエスト):
Request URL:http://127.0.0.1:3000/businesses
Request Method:OPTIONS
Status Code:404 Not Found
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:es-ES,es;q=0.8
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:127.0.0.1:3000
Origin:http://localhost:1234
Referer:http://localhost:1234/app/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
Response Headersview source
Connection:Keep-Alive
Content-Length:131852
Content-Type:text/html; charset=utf-8
Date:Mon, 04 Nov 2013 16:54:04 GMT
Server:WEBrick/1.3.1 (Ruby/2.0.0/2013-06-27)
X-Request-Id:25705159-fbfb-4830-a0f1-6610fa09b70e
X-Runtime:0.371000
アップデート
モデルパラメータを追加するときにコントローラを追加するのを忘れました:
$scope.createBusiness = function() {
console.log("Business.name=" + $scope.business.name);
$scope.business = Business.save($scope.business);
};
複数のフォームを持つ複数のビューがあるため、フォームを投稿するだけでなく、スコープ内にあるビジネス オブジェクト モデル (すべてのフォームのデータが入力されている) を投稿します。
アップデート
これは私の Rails Application_Controller (CORS 構成) です:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
# OJOJOOJO: Rober: I have commented this line which is provided by default with rails and added all code below in order to
# add CSRF protection
#protect_from_forgery with: :exception
protect_from_forgery
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers, :set_csrf_cookie_for_ng
# For all responses in this controller, return the CORS access control headers.
def cors_set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = "1728000"
end
# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.
def cors_preflight_check
if request.method == :options
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'
headers['Access-Control-Max-Age'] = '1728000'
render :text => '', :content_type => 'text/plain'
end
end
def set_csrf_cookie_for_ng
cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery?
end
protected
def verified_request?
super || form_authenticity_token == request.headers['X_XSRF_TOKEN']
end
end
ベストアンサー1
ついにうまくいきました。
私が読みたかった Angular と Rails 4 のすべての設定について説明します。
角度
アプリ.js:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers', 'myApp.i18n', 'demo']). config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) { $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common["X-Requested-With"];
}]);
注: もちろん、すべてのモジュールを含める必要はありません。
私からしてみれば:
<form novalidate="" name="createBusinessForm" ng-submit="setBusinessInformation()" class="css-form"> <label>* {{'BUSINESS_NAME' | translate}}</label> <input type="text" name="name" ng-model="business.name" class="input-xxlarge input-height-large" placeholder="{{'BUSINESS_NAME_PLACEHOLDER' | translate}}" required maxlength="80"> <span ng-show="createBusinessForm.name.$dirty && createBusinessForm.name.$error.required" class="text-error">Mandatory field.</span> <label>* {{'ID' | translate}}</label> <input type="text" ng-model="business.cif_nif" class="input-xlarge input-height-large" placeholder="{{'BUSINESS_ID_PLACEHOLDER' | translate}}" required maxlength="60"> <label>* {{'ADDRESS' | translate}}</label>
注: 必要な数のフィールドを定義し、データ バインディングを使用してオブジェクトに値を割り当てることができます。
私のコントローラーでは:
$scope.createBusiness = function() { $scope.business.type = $scope.type; $scope.business.plan = $scope.plan; $scope.business = Business.save($scope.business); $location.path('/user-dashboard'); };
注: すべての属性は、POST リクエストで送信する必要があります。フォームとは別に、Rails API に送信する前にオブジェクトにいくつかの新しい属性を割り当てることができます。リソース オブジェクトを持つサービスを使用して、POST リクエストを送信します。
私のサービスでは:
.factory('ビジネス',
function($resource){ var businesses = $resource('http://127.0.0.1\\:3000/:business', {business:'businesses'}, { query: {method:'GET', isArray: true}, save: {method:'POST', isArray: false} }); return businesses; }
);
注: Rails API を介して DB からビジネスを取得するための GET リクエストと POST リクエストがあります。
レール4
重要
ルート.rb
match "/businesses" => "application#index", via: :options
注: Angular サーバーが POST 要求の送信開始を事前にネゴシエートするために送信する OPTIONS 要求に一致する新しいエントリ。
アプリケーションコントローラ.rb
class ApplicationController < ActionController::Base before_filter :set_headers def index puts "Do nothing." render nothing: true end def set_headers puts 'ApplicationController.set_headers' if request.headers["HTTP_ORIGIN"] # better way check origin # if request.headers["HTTP_ORIGIN"] && /^https?:\/\/(.*)\.some\.site\.com$/i.match(request.headers["HTTP_ORIGIN"]) headers['Access-Control-Allow-Origin'] = request.headers["HTTP_ORIGIN"] headers['Access-Control-Expose-Headers'] = 'ETag' headers['Access-Control-Allow-Methods'] = 'GET, POST, PATCH, PUT, DELETE, OPTIONS, HEAD' headers['Access-Control-Allow-Headers'] = '*,x-requested-with,Content-Type,If-Modified-Since,If-None-Match,Auth-User-Token' headers['Access-Control-Max-Age'] = '86400' headers['Access-Control-Allow-Credentials'] = 'true' end end end
私のRailsコントローラ
def create puts 'Businesses_controller.create!!!!!' puts business_params.inspect # business_type object is recovered from db businessTypeName = params[:type] businessType = BusinessType.where(:name => businessTypeName).first ... end
注: ここで必要なことはすべて行ってください...