Ruby On Rails before_filter вызывается дважды?
Когда я отправляю запрос ajax на мой контроллер ruby, кажется, что функция before_filter вызывается дважды для каждого запроса ajax. Я использую before_filter для аутентификации.
Ajax-запрос, который я использую:
$.ajax({
type: 'GET',
url: 'URL_TO__RoR_Controller',
username: username,
password: password,
contentType: "application/json; charset=utf-8",
success: function(data){
console.log(data);
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(arguments);
}
});
Код RoR:
class Api::MyController < ApplicationController
before_filter :authenticate
attr_reader :current_user
def authenticate
print "===================================\n"
authenticate_or_request_with_http_basic do |username, password|
print "\n--------------------------------\n"
print username, password
print "\n--------------------------------\n"
@current_user = User.authenticate(username, password)
print "===================================\n"
end
end
def show
print "=================IN SHOW=================="
end
end
Ответ RoR на запрос ajax:
Started GET "URL_TO__RoR_Controller" for 127.0.0.1 at 2015-10-08 10:18:18 +0200
Processing by Api::MyController#show as JSON
Parameters: {"id"=>"show", "test"=>{}}
===================================
===================================
Filter chain halted as :authenticate rendered or redirected
Completed 401 Unauthorized in 1ms (ActiveRecord: 1.0ms)
Started GET "URL_TO__RoR_Controller" for 127.0.0.1 at 2015-10-08 10:18:19 +0200
Processing by Api::MyController#show as JSON
Parameters: {"id"=>"show", "test"=>{}}
===================================
--------------------------------
USERPASS
--------------------------------
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`authorized` = 1 AND `users`.`login` = 'USER' LIMIT 1
===================================
=================IN SHOW==================
Rendered URL_TO__RoR_Controller/show.json.rabl (0.8ms)
Completed 200 OK in 30ms (Views: 3.4ms | ActiveRecord: 1.7ms)
RoR config / rout.rb для этого одного контроллера:
Api::Application.routes.draw do
namespace :api, defaults: { format: :json } do
resources :MyController, only: [:show]
end
end
Таким образом, в основном функция аутентификации выполняется дважды для каждого отправляемого мной запроса ajax. Первая проверка подлинности не удалась. Это даже не попасть в authenticate_or_request_with_http_basic
функция. Второй раз все вроде нормально.
Очевидно, это не желаемое поведение. Что вызывает эту проблему?
Редактировать:
Хорошо, вот мои выводы при удалении before_filter:
1) При полном удалении before_filter проблема больше не возникает.
2) При сохранении / использовании before_filter, но замене authenticate_or_request_with_http_basic на 'true' следующим образом:
def authenticate
true
end
проблема тоже не возникает. Таким образом, проблема, кажется, вызвана authenticate_or_request_with_http_basic?
1 ответ
Этого не произойдет, если не будет вызвано как-то.
И, увидев, что запросы отправляются 1 секунда между собой, это говорит о том, что ваш Ajax отправляется дважды:
127.0.0.1 at 2015-10-08 10:18:18 +0200
127.0.0.1 at 2015-10-08 10:18:19 +0200
Хотя сам по себе этот ответ не является ответом, существует несколько способов его отладки:
- Во-первых, вы должны понимать, что это не произойдет само по себе
- Процесс "отладки" - это просто случай выявления и разрешения проблемы.
- Я не думаю, что Rails дважды будет запускать действие контроллера без его вызова
Таким образом, вы должны взглянуть на различные элементы проблемы:
Во-первых, ваш Ajax- запрос запускается дважды.
Вы предоставили следующий код:
$.ajax({
type: 'GET',
url: 'URL_TO__RoR_Controller',
username: username,
password: password,
contentType: "application/json; charset=utf-8",
success: function(data){
console.log(data);
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(arguments);
}
});
Это не показывает нам, как это связано с элементами на вашей странице. Я бы предположил, что у вас проблемы с Turbolinks.
Первый шаг к отладке - убедиться, что привязка JS не затруднена. В частности, вы хотите убедиться, что вы используете в своих интересах turbolinks
крючки (page:load
):
#app/assets/javascripts/application.js
bind = function() {
$(".element").on("click", function() {
// Ajax
});
};
$(document).on("ready page:load", bind);
Или вы можете делегировать из документа:
#app/assets/javascripts/application.js
$(document).on("click", ".element", function() {
// Ajax
});
Во-вторых, кажется, что ваши действия контроллера вызываются дважды, но это не только before_filter
... это весь поток (во втором случае).
Filter chain halted as :authenticate rendered or redirected
Completed 401 Unauthorized in 1ms (ActiveRecord: 1.0ms)
Единственная причина первой before_filter
не стрелял, потому что ты не был аутентифицирован. Я не знаю, как вы аутентифицируете пользователей, но если бы вы смогли это сделать, я бы подумал, что этот процесс произойдет.
Таким образом, возникает вопрос: как получить первый запрос?
Если вы делаете что-то по-разному между двумя запросами, мы должны это увидеть. Не то чтобы я думаю, что вы знаете, это происходит автоматически:)
-
Это можно сделать резервной копией, наблюдая "сетевые" запросы, отправленные на сервер с помощью ajax:
Наконец, вы хотите сделать некоторые тесты без before_filter
метод, чтобы увидеть, будет ли это работать. Возможно, вы не получили правильные токены аутентификации или другие проблемы в промежуточном программном обеспечении.