agm*_*min 2 ruby api session ruby-on-rails ruby-on-rails-3
背景:我有一个 API 驱动的 Rails 3 应用程序,利用 DataMapper(DM) 和 DM 适配器与 API 进行交互。每个 DM 模型都有一个相应的 REST-ish API 端点,就像使用 Rails 脚手架所获得的那样。API 请求时需要各种标头,包括 API 令牌、密钥、ID 等。标头与请求的数据无关,它们仅用于授权和跟踪目的。许多这样的令牌存储在会话中。我想要一种干净的方法来使这些 API 标头在请求期间可用于任何模型。
可能的解决方案:
显而易见的答案是将哈希或其他对象中的令牌从控制器传递到模型。控制器操作可能具有以下内容:@user = User.find(params[:id], api_headers)。
问题是需要重写任何模型方法来接受附加api_headers对象。不包括 Rails 和 DataMapper 定义的方法,应用程序模型中已经定义了数百种需要重写的方法。因此,我排除了重写的可能性,而且这似乎也不是一个好的解决方案,因为它需要覆盖大量荒谬的 DM 方法,如User#find上面的示例。
我可以捕获ArgumentErrorDM 基类上的任何 ' 并检查最后一个参数是否是对象api_headers,然后将值设置为实例变量并调用请求的方法。这个思维练习已经让我在处理可选参数等方面感到畏缩。如果给予足够长的时间,我可能会创建一个功能性的弗兰肯斯坦,它应该让我被解雇,但可能不会。
在应用程序控制器中设置 abefore_filter将会话存储的 API 标头转储到单例ApiHeaders对象中。然后,任何发出 API 请求的模型都可以获取具有所需 API 标头的单例。
after_filter应用程序控制器上的附加* 会在请求结束时将所有属性设置为单例,以防止请求之间泄漏标头nil。ApiHeaders
这是目前我的首选解决方案,但我不喜欢 API 标头值在after_filter未调用的情况下可能会转移到其他请求中。我不知道在哪些情况下可能会发生这种情况(也许是在应用程序错误中?),这引起了担忧。我所知道的是,这些价值观并不一定会随着请求而消失。
放弃对 DataMapper 和自定义 API 适配器的支持,并手动进行所有 API 调用,传递所有必需的 API 标头。除了我没有时间进行这种级别的重写之外,如果您必须投入大量资源来支持自定义身份验证方案,为什么还要使用框架呢?
将这些讨厌的 API 令牌从会话获取到应用程序内部的最干净方法是什么?这些令牌可以随每个 API 请求一起发送?我希望有一个比上面列出的更好的解决方案。
* 别名为after_action
我使用request_store gem设置当前用户和用户模型上的请求信息,它只是线程本地存储上的一个小垫片,并进行了一些清理。
这使得可以通过 User 类从我的任何模型中获取信息。我有User.current,User.request并且User.location可以在任何需要的地方使用。
您的控制器只需进行设置User.current,并User.request在对用户进行身份验证后即可。
用户模型示例:
# models/user.rb
require 'request_store'
class User
def self.current
RequestStore.store[:current_user]
end
def self.current=(user)
RequestStore.store[:current_user] = user
end
def self.request
RequestStore.store[:current_request]
end
def self.request=(request)
# stash the request so things like IP address and GEO-IP based location is available to other models
RequestStore.store[:current_request] = request
end
def self.location
# resolve the location just once per request
RequestStore.store[:current_location] ||= self.request.try(:location)
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2853 次 |
| 最近记录: |