-
-
Save godfat/5676447 to your computer and use it in GitHub Desktop.
require 'rest-core' | |
module RestCore | |
middleware = Class.new | |
middleware.module_eval do | |
def initialize app | |
@app = app | |
end | |
def call env, &k | |
puts "Calling" | |
@app.call(env, &k) | |
end | |
end | |
Circular = Builder.client do | |
use middleware | |
end | |
Circular::Middleware = middleware | |
end | |
puts RC::Circular | |
puts RC::Circular::Middleware | |
puts RC::Circular.new.head('http://example.com/') |
require 'rest-core' | |
module RestCore | |
middleware = Class.new | |
middleware.module_eval do | |
def initialize app | |
@app = app | |
end | |
def call env, &k | |
puts env['secret'] | |
@app.call(env, &k) | |
end | |
end | |
Secret = Builder.client(:secret) do | |
use middleware | |
end | |
Secret::Middleware = middleware | |
end | |
puts RC::Secret.new(:secret => 'mission').head('http://example.com/') |
require 'rest-core/middleware' | |
require 'rest-core/util/hmac' | |
class RestCore::Signature | |
def self.members; [:secret]; end | |
include RestCore::Middleware | |
def call env, &k | |
uri = request_uri(env) | |
sig = Hmac.sha1(secret(env), uri) | |
app.call(env.merge(REQUEST_QUERY => {}, | |
REQUEST_PATH => "#{uri}&Signature=#{sig}", &k)) | |
end | |
end |
你在什麼情況下會碰到?試了一下試不出來
啊謝謝,我碰到的情況是忘了用 * 號時,c.get('getCurrTime')
報錯後,console我就有五秒鐘可以作任何事,之後就突然冒出這訊息結束 console。
2.0.0-p0 :003 > c.get('getCurrTime')TypeError: no implicit conversion of nil into String
from /Code/rest-more/rest-core/lib/rest-core/util/hmac.rb:17:in `digest'
...
from /.rvm/rubies/ruby-2.0.0-p0/bin/irb:16:in `<main>'
2.0.0-p0 :004 > a = 1
=> 1
2.0.0-p0 :005 > b = 2
=> 2
2.0.0-p0 :006 > c = 3
=> 3
2.0.0-p0 :007 > /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/input-method.rb:152:in `readline': execution expired (Timeout::Error)
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/input-method.rb:152:in `gets'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:472:in `block (2 levels) in eval_input'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:624:in `signal_status'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:471:in `block in eval_input'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:190:in `call'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:190:in `buf_input'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:105:in `getc'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/slex.rb:206:in `match_io'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/slex.rb:76:in `match'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:290:in `token'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:266:in `lex'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:237:in `block (2 levels) in each_top_level_statement'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `loop'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `block in each_top_level_statement'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `catch'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `each_top_level_statement'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:488:in `eval_input'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:397:in `block in start'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:396:in `catch'
from /.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:396:in `start'
from /.rvm/rubies/ruby-2.0.0-p0/bin/irb:16:in `<main>'
我知道是什麼原因了 O_o
這跟 irb 或 rib 無關,應該也算是 bug 吧 @@"
是我的 timeout 實作造成的
仔細想想這樣做是不太好...
我想想看要怎麼修比較好
嗯辛苦了XD
想問一下概念問題,可以看看我的理解有沒有錯誤嗎:
middleware 的 members 有兩個功能,首先是用來在 Client Class 設立時預備 middleware 層級的變數用(如預設 base url)。不過他也有第二個功能,是開個介面能去抓 env 裡面的變數,所以像是 secret 這類 instance 層級的東西還是需要設立 members才有方便的介面跟env取值。
Builder.client() 裡面要丟進去的 symbols 那部份我讀不太懂。是不是代表宣告 client instance variable呢?要產生新的 client instance 時用 hash 丟這些參數進去就會存到特殊的地方而不是當作 query param,如 RC::Facebook 的 app_id?
這也讓我我不懂為何 Yahoo的 secret 不能放在 client builder 裡面,這是 client instance 層級的變數,在 Client.new 時傳入(跟 api_key 是一對的)。
謝謝解惑~
啊然後想問,要是得把 api_key放在每個 request 中,這是那個 default_payload 還是 default_query 的範圍嗎?
對,一方面給一些方便的 methods 可用,另一方面則是讓 client 也可以記得一份可改變的設定(變數)
對,Builder.client
給的參數是額外需要記得的變數,確實如 RC::Facebook
的 app_id
, 不過這裡並沒有例外,這個 app_id
也同樣會傳到 env 裡面,只是 middleware 裡面可能不會用到而已。
意思就是,在之前的版本裡(現已修好),如果 Builder.client
和 middleware 都給 secret
, 則 client 實際上會有兩個 secret
(!) 修正好的版本在所有的 attributes 中取 uniq
, 因此 secret 會只剩一個。
這樣並不會造成任何問題(在新的版本裡),只是沒有意義而已。也可以寫成:
class Signature
def initialize app; @app = app; end
def call env, &k
puts env['secret']
app.call(&k)
end
end
Client = RC::Builder.client(:secret){ use Signature }
也就是說,middleware 裡面就不自己記得一份 secret 了,一律靠 client 傳過去。這樣做的缺點是,使用 middleware 的人要自己記得這個 middleware 可能需要一份 secret 傳進去。
至於 api_key 如果要放在每個 request 中,那取決於要放在 query 或是 payload 甚或 headers 裡,
我會用對應的 middleware 並定義 default_query. 範例:
Client = RC::Builder.client(:api_key){ use RC::DefaultQuery }
class Client
def default_query
{:api_key => api_key}
end
end
這樣 client 可記得 api_key, 同時會自動夾在 query 裡面。payload 或 headers 亦然。
請問一下,你說的 dry run是原本就會丟出 timeout 囉?
2.0.0-p0 :002 > client = RC::Facebook.new
=> #<struct RestCore::Facebook timeout=10, site="https://gra..., headers={"Accept"=>"..., access_token=nil, log_method=nil, cache=nil, expires_in=600, error_handler=#<Proc:0x007..., error_detector=#<Proc:0x007..., json_response=true, defaults={:old_site=>..., data={}, app_id=nil, secret=nil, old_site="https://api...>
2.0.0-p0 :003 > client.request_full({RC::REQUEST_PATH => '/'}, client.dry)
=> {"REQUEST_METHOD"=>:get, "REQUEST_PATH"=>"https://graph.facebook.com//", "REQUEST_QUERY"=>{}, "REQUEST_PAYLOAD"=>{}, "REQUEST_HEADERS"=>{"Accept"=>"application/json", "Accept-Language"=>"en-us"}, "core.fail"=>[], "core.log"=>[#<struct RestCore::Event::Requested duration=0.010871, message="GET https://graph.facebook.com//">], "timeout"=>10, "site"=>"https://graph.facebook.com/", "headers"=>{"Accept"=>"application/json", "Accept-Language"=>"en-us"}, "access_token"=>nil, "log_method"=>nil, "cache"=>nil, "expires_in"=>600, "error_handler"=>#<Proc:0x007fd739686420@Code/rest-more/lib/rest-core/client/facebook.rb:18 (lambda)>, "error_detector"=>#<Proc:0x007fd7396864c0@Code/rest-more/lib/rest-core/client/facebook.rb:19 (lambda)>, "json_response"=>true, "defaults"=>{:old_site=>"https://api.facebook.com/"}, "data"=>{}, "app_id"=>nil, "secret"=>nil, "old_site"=>"https://api.facebook.com/", "async.callback"=>false, "async.timer"=>#<RestCore::Timeout::TimerThread:0x007fd7396a6dd8 @timeout=10, @error=#<Timeout::Error: execution expired>, @block=#<Proc:0x007fd7396a6d88@Code/rest-more/rest-core/lib/rest-core/middleware/timeout/timer_thread.rb:9 (lambda)>, @canceled=false, @thread=#<Thread:0x007fd7396a6d60 sleep>>, "RESPONSE_BODY"=>nil}
2.0.0-p0 :004 > .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/input-method.rb:152:in `readline': execution expired (Timeout::Error)
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/input-method.rb:152:in `gets'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:472:in `block (2 levels) in eval_input'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:624:in `signal_status'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:471:in `block in eval_input'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:190:in `call'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:190:in `buf_input'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:105:in `getc'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/slex.rb:206:in `match_io'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/slex.rb:76:in `match'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:290:in `token'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:266:in `lex'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:237:in `block (2 levels) in each_top_level_statement'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `loop'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `block in each_top_level_statement'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `catch'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `each_top_level_statement'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:488:in `eval_input'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:397:in `block in start'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:396:in `catch'
from .rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/irb.rb:396:in `start'
from .rvm/rubies/ruby-2.0.0-p0/bin/irb:16:in `<main>'
看了一下,發現因為少打一個
*
, 在 Client.new 那邊誤傳了 array 進去因此
api_key
跟secret
沒設進去。改成這樣可動:我自己是都用 rib, 目前沒碰過那個狀況
我試試看能不能在 irb 下重現?看起來不應該有這個錯