Подтвердить что ты не робот

Добавить ключ api для каждого запроса в ActiveResource

У меня есть 2 RESTful Rails приложения, которые я пытаюсь поговорить друг с другом. Оба они написаны в Rails 3 (beta3 на данный момент). Запросы к службе потребуют использования ключа api, который является всего лишь параметром, который должен выполняться по каждому запросу. Я не могу найти какую-либо информацию о том, как это сделать.

Вы определяете URL-адрес, к которому подключается ресурс, с помощью метода site =. Должен быть эквивалентный метод query_params = или аналогичный.

Есть одно хорошее сообщение в блоге, которое я нашел, связанное с этим, и с октября 2008 года, поэтому не очень полезно для Rails 3.

Обновление. У меня была мысль. Будет ли на это ответным промежуточным программным обеспечением Rack или Metal? Он может просто пройти через запрос, нажав на него api_key.

4b9b3361

Ответ 1

Использовать модель # prefix_options, которая является хешем для передачи параметров в строку запроса (или даже в качестве подстановок для частей Model.prefix, например "/myresource/: param/", будет заменена значением prefix_options [: param ]. В строку запроса будут добавлены любые хеш-ключи, не найденные в префиксе, и это то, что мы хотим в вашем случае).

class Model < ActiveResource::Base
  class << self
    attr_accessor :api_key
  end

  def save
    prefix_options[:api_key] = self.class.api_key
    super
  end
end

Model.site = 'http://yoursite/'
Model.api_key = 'xyz123'
m = Model.new(:field_1 => 'value 1')
# hits http://yoursite:80/models.xml?api_key=xyz123
m.save

Ответ 2

Недавно я столкнулся с подобной проблемой, если вы на Rails3, она поддерживает использование настраиваемого заголовка, что значительно облегчает жизнь в этих ситуациях.

С той стороны, с которой вы делаете запрос, добавьте

headers['app_key'] = 'Your_App_Key'

для класса, который вы наследуете от ActiveResource:: Base

На сервере, для аутентификации, просто получите его как

request.headers['HTTP_APP_KEY']

Пример:

class Magic < ActiveResource::Base
    headers['app_key'] = 'Your_App_Key'
end

теперь Magic.get, Magic.find, Magic.post все отправят app_key

Ответ 3

У меня гораздо приятнее решение! Я пытаюсь использовать Rack в промежуточном программном обеспечении, но я не нахожу решения таким образом....

Я предлагаю вам этот модуль для переопределения методов ActiveReouse:: Base

Добавьте этот lib в каталог /lib/active _resource/extend/, не забудьте раскомментировать "config.autoload_paths + =% W (# {config.root}/lib)" в config/application.rb

module ActiveResource #:nodoc:
  module Extend
    module AuthWithApi
      module ClassMethods
        def element_path_with_auth(*args)
          element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
        def new_element_path_with_auth(*args)
          new_element_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
        def collection_path_with_auth(*args)
          collection_path_without_auth(*args).concat("?auth_token=#{self.api_key}")
        end
      end

      def self.included(base)
        base.class_eval do
          extend ClassMethods
          class << self
            alias_method_chain :element_path, :auth
            alias_method_chain :new_element_path, :auth
            alias_method_chain :collection_path, :auth
            attr_accessor :api_key
          end
        end
      end  
    end
  end  
end

в модели

class Post < ActiveResource::Base
  include ActiveResource::Extend::AuthWithApi

  self.site = "http://application.localhost.com:3000/"
  self.format = :json

  self.api_key = 'jCxKPj8wJJdOnQJB8ERy'

  schema do
    string  :title
    string  :content
  end

end

Ответ 4

На основании ответа Джоэла Аземара, но мне пришлось внести некоторые изменения. Прежде всего, в массиве активных ресурсов, который я использовал (2.3.8), нет "new_element_path", поэтому сглаживание явно не получилось. Во-вторых, я обновил способ добавления токена в запрос, потому что, как и было, он сломается, как только вы добавите больше параметров самостоятельно. Например. запрос http://example.com/api/v1/clients.xml?vat=0123456789?token=xEIx6fBsxy6sKLJMPVM4 (уведомление? токен = i.o. & токен =)

Здесь мой обновленный фрагмент auth_with_api.rb;

module ActiveResource #:nodoc:
  module Extend
    module AuthWithApi
      module ClassMethods
        def element_path_with_auth(id, prefix_options = {}, query_options = nil)
          query_options.merge!({:token => self.api_key})
          element_path_without_auth(id, prefix_options, query_options)
        end
        def collection_path_with_auth(prefix_options = {}, query_options = nil)
          query_options.merge!({:token => self.api_key})
          collection_path_without_auth(prefix_options, query_options)
        end
      end

      def self.included(base)
        base.class_eval do
          extend ClassMethods
          class << self
            alias_method_chain :element_path, :auth
            # alias_method_chain :new_element_path, :auth
            alias_method_chain :collection_path, :auth
            attr_accessor :api_key
          end
        end
      end  
    end
  end
end

Ответ 5

Активный ресурс в настоящее время не имеет хорошего способа передать ключ api удаленной службе. Передача api_key в качестве параметра добавит его к атрибутам объектов в удаленной службе, я предполагаю, что это не то поведение, которое вы хотели бы. Это, конечно, не то поведение, в котором я нуждался.

Ответ 6

Объект активного ресурса ведет себя как объект (упрощенная) Active Record. Если вы хотите передать новый параметр, вы можете установить его на AR-объект, добавив его как атрибут. например:

jane = Person.create(:first => 'Jane', :last => 'Doe', :api_key => THE_API_KEY)

он должен передать api_key в качестве параметра вместе со всеми остальными.

Ответ 7

Я бы рекомендовал, чтобы у вас был базовый класс, наследующий от ActiveResource::Base и переопределяющий методы класса self.collection_path и self.element_path, чтобы всегда вводить API KEY что-то вроде:

class Base < ActiveResource::Base
  def self.collection_path(prefix_options = {}, query_options = {})
   super(prefix_options, query_options.merge(api_key: THE_API_KEY))
  end

  def self.element_path(id, prefix_options = {}, query_options = {})
    super(id, prefix_options, query_options.merge(api_key: THE_API_KEY))
  end
end

class User < Base; end

User.all # GET /users/?api_key=THE_API_KEY

Это всегда будет вводить ваш API_KEY в вызовы метода ActiveResource.