Добавить ключ API к каждому запросу в ActiveResource - PullRequest
20 голосов
/ 27 мая 2010

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

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

Я нашел один хороший пост в блоге, связанный с этим, и он был написан в октябре 2008 года, поэтому не совсем полезен для Rails 3.

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

Ответы [ 7 ]

21 голосов
/ 14 апреля 2011

Используйте модель # 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
10 голосов
/ 29 сентября 2011

Недавно я столкнулся с подобной проблемой: если вы работаете на 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 все отправят ключ приложения

4 голосов
/ 25 мая 2011

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

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

Добавьте эту библиотеку в каталог / lib / active_resource / extend /, не забудьте раскомментировать
"config.autoload_paths + =% W (# {config.root} / lib)" in 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
3 голосов
/ 06 марта 2012

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

Вот мой обновленный фрагмент 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
2 голосов
/ 29 апреля 2016

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

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.

2 голосов
/ 14 января 2011

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

1 голос
/ 10 декабря 2010

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

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

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

...