Ruby on rails Rails中的Async#u Sinatra:异步操作可以';无法写入共享会话
我在一个Rails项目中有一个Sinatra课程。它使用eventmachine和async_sinatra对外部站点进行异步调用。我希望写入会话对象(理想情况下,与Rails使用的对象相同),但到目前为止,我只能:Ruby on rails Rails中的Async#u Sinatra:异步操作可以';无法写入共享会话,ruby-on-rails,session,asynchronous,sinatra,eventmachine,Ruby On Rails,Session,Asynchronous,Sinatra,Eventmachine,我在一个Rails项目中有一个Sinatra课程。它使用eventmachine和async_sinatra对外部站点进行异步调用。我希望写入会话对象(理想情况下,与Rails使用的对象相同),但到目前为止,我只能: 从Rails写入单独的会话对象(默认情况下,Sinatra将其会话命名为与Rails不同的名称) 仅为同步调用写入同一会话 当我进行异步调用时,用async_sinatra代码编写的会话不会被推送到客户机。我怀疑有两件事正在发生: 标头已经发送到客户端,并且存储会话的本地变量
- 从Rails写入单独的会话对象(默认情况下,Sinatra将其会话命名为与Rails不同的名称)
- 仅为同步调用写入同一会话
- 标头已经发送到客户端,并且存储会话的本地变量(在Sinatra中)将在操作结束时刷新。客户端永远不会看到来自服务器的将此数据保存到cookie的请求
- 头被发送到客户端,但Rails立即发送另一个,指示客户端将Rails存储在其
变量中的内容写入cookie,覆盖Sinatra写入的内容会话
class ExternalCall < Sinatra::Base
use ActionDispatch::Session::CookieStore
register Sinatra::Async
get '/sinatra/local' do
session[:demo] = "sinatra can write to Rails' session"
end
aget '/sinatra/goog' do
session[:async_call]="async sinatra calls cannot write to Rails' session"
make_async_req :get, "http://www.google.com/" do |http_callback|
if http_callback
session[:em_callback] = "this also isn't saving for me"
else
headers 'Status' => '422'
end
async_schedule { redirect '/' }
end
end
helpers do
def make_async_req(method, host, opts={}, &block)
opts[:head] = { 'Accept' => 'text/html', 'Connection' => 'keep-alive' }
http = EM::HttpRequest.new(host)
http = http.send(method, {:head => opts[:head], :body => {}, :query => {}})
http.callback &block
end
end
end
类外部调用“422”
结束
异步_调度{redirect'/'}
结束
结束
帮手
def make_async_req(方法、主机、选项={}和块)
选项[:head]={'Accept'=>'text/html','Connection'=>'keep alive'}
http=EM::HttpRequest.new(主机)
http=http.send(方法,{:head=>opts[:head],:body=>{},:query=>{})
http.callback&block
结束
结束
结束
编辑7/15:
更改了Github上的代码以包括异步机架。Async sinatra可以在会话未与Rails共享时写入会话。比较
主会话
和分段会话
分支的行为差异。(或者在master
分支上,将use ActionDispatch::Session::CookieStore
更改为enable:sessions
)这是因为async\u sinatra
默认使用throw:async
,有效地跳过了用于存储内容的会话中间件逻辑。您可以这样覆盖:
helpers do
def async_response
[-1, {}, []]
end
end
嗯,这似乎对我不起作用。我已经尝试在我自己的代码中完成这项工作,也尝试在这个项目中使用monkey patching
async\u sinatra
。我注意到,在async\u sinatra
代码中,您链接到aget
的代码专门单独安排了get和head。我想知道这是否是问题的根源。我相信每个请求只能返回一个头。我的同事们决定使用某种服务器端会话,但我仍然想弄明白这一点,希望能让EM和Async_sinatra更有用。哦,是的,我也意识到了这一点。标题仍然被忽略。尝试使用。事实证明,我们实际上在我们的主应用程序中使用了它,而我忘了在这个演示项目中包含它。我已经更新了我在Github上的演示项目以及我的问题。演示代码表明,即使调用了所有中间件,也存在会话共享问题。对不起,我没有注意到您使用的是Rails会话中间件。问题是:您的会话中间件不知道如何处理异步请求。使用throw:async
生成cookie的代码永远不会运行,使用[-1,{},[]]
该代码将修改Thin永远不会使用的头散列。我认为如果不让Rails和Rack代码弄脏你的双手,你就无法解决这个问题。我认为还有另一个解决方案:你可以尝试存储对[-1,{},[]
中传递的散列的引用,然后将其合并到会话散列中。但是,如果任何中间件返回一个新的哈希值而不是修改该哈希值,那么您的SOL。