Ruby on rails Rails中的Async#u Sinatra:异步操作可以';无法写入共享会话

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课程。它使用eventmachine和async_sinatra对外部站点进行异步调用。我希望写入会话对象(理想情况下,与Rails使用的对象相同),但到目前为止,我只能:

  • 从Rails写入单独的会话对象(默认情况下,Sinatra将其会话命名为与Rails不同的名称)
  • 仅为同步调用写入同一会话
当我进行异步调用时,用async_sinatra代码编写的会话不会被推送到客户机。我怀疑有两件事正在发生:

  • 标头已经发送到客户端,并且存储会话的本地变量(在Sinatra中)将在操作结束时刷新。客户端永远不会看到来自服务器的将此数据保存到cookie的请求

  • 头被发送到客户端,但Rails立即发送另一个,指示客户端将Rails存储在其
    会话
    变量中的内容写入cookie,覆盖Sinatra写入的内容

不管是哪种方式,我只想在Sinatra和Rails中获得简单的会话功能。解释一下我做错了什么也很好:)

代码的完整工作副本是,但我认为问题具体存在于该代码中:

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。