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

Хотя сам по себе этот ответ не является ответом, существует несколько способов его отладки:

  1. Во-первых, вы должны понимать, что это не произойдет само по себе
  2. Процесс "отладки" - это просто случай выявления и разрешения проблемы.
  3. Я не думаю, что 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 метод, чтобы увидеть, будет ли это работать. Возможно, вы не получили правильные токены аутентификации или другие проблемы в промежуточном программном обеспечении.

Другие вопросы по тегам