Rails API with devise, can't 运行 POST #create method with JSON call from client
Rails API with devise, can't run POST #create method with JSON call from client
所以我正在尝试用设计创建一个 Rails API。我的客户端可以很好地使用 GET,但我不能执行 POST 类型的调用。如果我尝试创建一个用户,我会不断收到以下设计 html 表单作为响应。
<h2>Sign up</h2>
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="RGZxLuXcOCbxKVdpFc/wSAKEp3wcxqpfnvmv0nstEcOppPyViWcmdu+dPt84XQeSkCmwRg0REZN+vTdX1j+MOQ==" />
<div id="error_explanation">
<h2>2 errors prohibited this user from being saved:</h2>
<ul><li>Email can't be blank</li><li>Password can't be blank</li></ul>
</div>
<div class="field">
<div class="field_with_errors"><label for="user_email">Email</label></div><br />
<div class="field_with_errors"><input autofocus="autofocus" type="email" name="user[email]" id="user_email" /></div>
</div>
<div class="field">
<div class="field_with_errors"><label for="user_password">Password</label></div>
<em>(4 characters minimum)</em>
<br />
<div class="field_with_errors"><input autocomplete="off" type="password" name="user[password]" id="user_password" /></div>
</div>
<div class="field">
<label for="user_password_confirmation">Password confirmation</label><br />
<input autocomplete="off" type="password" name="user[password_confirmation]" id="user_password_confirmation" />
</div>
<div class="actions">
<input type="submit" name="commit" value="Sign up" />
</div>
</form>
<a href="/users/sign_in">Log in</a><br />
<a href="/users/confirmation/new">Didn't receive confirmation instructions?</a><br />
有趣的是,一开始我会得到一个 "Can't verify CSRF token authenticity" 错误,所以我在我的 [=62= 中添加了 beforeSend ] 称呼。这将改变我对 OPTIONS 的调用,即使它被指定为 POST。
我的电话:
$(document).on('page:change', function(){
$('body').on('submit', 'form.create_new_user', function(e){
e.preventDefault();
var user_data = $(this).serializeJSON();
$.ajax({
url: Host.address + '/users',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
type: 'post',
datatype:'json',
data: {info: {full_name: user_data.full_name,
email: user_data.email,
password: user_data.password,
password_confirmation: user_data.password_confirmation}}
}).done(function(response){
console.log(response)
if (response.success.success) {
logInGoToWithNotice(response, '/', 'Thank you for signig up');
} else{
alert("User wasn't created. Please try again.")
};
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
并且 API 这样做:
Started OPTIONS "/users" for ::1 at 2015-09-30 14:09:49 +0200
ActionController::RoutingError (uninitialized constant RegistrationsController):
...
如果我现在删除 beforeSend,我会再次得到表格,只是 "Can't verify CSRF token authenticity" 错误不会在那里,但我会成功 POST,仍然 returns html 形式。
Started POST "/users" for ::1 at 2015-09-30 14:25:57 +0200
Processing by Devise::RegistrationsController#create as */*
Parameters: {"info"=>{"full_name"=>"User Admin", "email"=>"user.admin@email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
(0.1ms) BEGIN
(0.1ms) ROLLBACK
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/shared/_links.html.erb (0.2ms)
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/registrations/new.html.erb (3.5ms)
Completed 200 OK in 9ms (Views: 4.7ms | ActiveRecord: 0.2ms)
现在,如果我查看我的用户控制器,我可以看到我什至从未 运行 我的 #create,因为它从不打印 p "C"*99
class Users::RegistrationsController < Devise::RegistrationsController
def create
p "C"*99
user = User.new
user.full_name = user_params[:full_name]
user.email = user_params[:email].downcase
user.password = user_params[:password]
user.password_confirmation = user_params[:password_confirmation]
if user.save
render json: {success:{success: true, user_id: user.id, errorMessage: nil, errorNumber: 201}}
else
render json: {success:{success: false, errorMessage: user.errors.messages.to_s, errorNumber: 400}}
end
end
end
为什么我不能调用它?我需要做什么才能让它起作用?
第一
这个问题是因为跨站点脚本问题。 client url
不同于 api url
。 HTTP method OPTIONS
是浏览器发出的 飞行前 请求,用于确定是否应允许跨域 AJAX
请求。
如果允许跨域 AJAX
请求,将发送实际请求 POST
。
所以你需要在你的服务器上允许跨域AJAX
请求。
第二
确保您的 routes.rb
设置正确。
您需要配置您的设备并指示他使用您的 customized registration_controller
而不是 default devise registration controller
将 routes.rb
中的 devise_for :users
调整为如下所示:
devise_for :users, controllers: { registrations: "users/registrations"}
假设 customized registration class
存在于 users
文件夹中
所以我正在尝试用设计创建一个 Rails API。我的客户端可以很好地使用 GET,但我不能执行 POST 类型的调用。如果我尝试创建一个用户,我会不断收到以下设计 html 表单作为响应。
<h2>Sign up</h2>
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="RGZxLuXcOCbxKVdpFc/wSAKEp3wcxqpfnvmv0nstEcOppPyViWcmdu+dPt84XQeSkCmwRg0REZN+vTdX1j+MOQ==" />
<div id="error_explanation">
<h2>2 errors prohibited this user from being saved:</h2>
<ul><li>Email can't be blank</li><li>Password can't be blank</li></ul>
</div>
<div class="field">
<div class="field_with_errors"><label for="user_email">Email</label></div><br />
<div class="field_with_errors"><input autofocus="autofocus" type="email" name="user[email]" id="user_email" /></div>
</div>
<div class="field">
<div class="field_with_errors"><label for="user_password">Password</label></div>
<em>(4 characters minimum)</em>
<br />
<div class="field_with_errors"><input autocomplete="off" type="password" name="user[password]" id="user_password" /></div>
</div>
<div class="field">
<label for="user_password_confirmation">Password confirmation</label><br />
<input autocomplete="off" type="password" name="user[password_confirmation]" id="user_password_confirmation" />
</div>
<div class="actions">
<input type="submit" name="commit" value="Sign up" />
</div>
</form>
<a href="/users/sign_in">Log in</a><br />
<a href="/users/confirmation/new">Didn't receive confirmation instructions?</a><br />
有趣的是,一开始我会得到一个 "Can't verify CSRF token authenticity" 错误,所以我在我的 [=62= 中添加了 beforeSend ] 称呼。这将改变我对 OPTIONS 的调用,即使它被指定为 POST。
我的电话:
$(document).on('page:change', function(){
$('body').on('submit', 'form.create_new_user', function(e){
e.preventDefault();
var user_data = $(this).serializeJSON();
$.ajax({
url: Host.address + '/users',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
type: 'post',
datatype:'json',
data: {info: {full_name: user_data.full_name,
email: user_data.email,
password: user_data.password,
password_confirmation: user_data.password_confirmation}}
}).done(function(response){
console.log(response)
if (response.success.success) {
logInGoToWithNotice(response, '/', 'Thank you for signig up');
} else{
alert("User wasn't created. Please try again.")
};
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
并且 API 这样做:
Started OPTIONS "/users" for ::1 at 2015-09-30 14:09:49 +0200
ActionController::RoutingError (uninitialized constant RegistrationsController):
...
如果我现在删除 beforeSend,我会再次得到表格,只是 "Can't verify CSRF token authenticity" 错误不会在那里,但我会成功 POST,仍然 returns html 形式。
Started POST "/users" for ::1 at 2015-09-30 14:25:57 +0200
Processing by Devise::RegistrationsController#create as */*
Parameters: {"info"=>{"full_name"=>"User Admin", "email"=>"user.admin@email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
(0.1ms) BEGIN
(0.1ms) ROLLBACK
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/shared/_links.html.erb (0.2ms)
Rendered /Users/antonpot/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/devise-3.5.2/app/views/devise/registrations/new.html.erb (3.5ms)
Completed 200 OK in 9ms (Views: 4.7ms | ActiveRecord: 0.2ms)
现在,如果我查看我的用户控制器,我可以看到我什至从未 运行 我的 #create,因为它从不打印 p "C"*99
class Users::RegistrationsController < Devise::RegistrationsController
def create
p "C"*99
user = User.new
user.full_name = user_params[:full_name]
user.email = user_params[:email].downcase
user.password = user_params[:password]
user.password_confirmation = user_params[:password_confirmation]
if user.save
render json: {success:{success: true, user_id: user.id, errorMessage: nil, errorNumber: 201}}
else
render json: {success:{success: false, errorMessage: user.errors.messages.to_s, errorNumber: 400}}
end
end
end
为什么我不能调用它?我需要做什么才能让它起作用?
第一
这个问题是因为跨站点脚本问题。 client url
不同于 api url
。 HTTP method OPTIONS
是浏览器发出的 飞行前 请求,用于确定是否应允许跨域 AJAX
请求。
如果允许跨域 AJAX
请求,将发送实际请求 POST
。
所以你需要在你的服务器上允许跨域AJAX
请求。
第二
确保您的 routes.rb
设置正确。
您需要配置您的设备并指示他使用您的 customized registration_controller
而不是 default devise registration controller
将 routes.rb
中的 devise_for :users
调整为如下所示:
devise_for :users, controllers: { registrations: "users/registrations"}
假设 customized registration class
存在于 users
文件夹中