Rails中的Async_Sinatra:异步操作无法写入共享会话

时间:2011-07-14 05:51:42

标签: ruby-on-rails session asynchronous sinatra eventmachine

我在Rails项目中有一个Sinatra类。它使用eventmachine和async_sinatra对外部站点进行异步调用。我想写一个会话对象(理想情况下,与Rails使用的对象相同),但到目前为止我只能:

  • 从Rails写入一个单独的会话对象(默认情况下,Sinatra将其会话命名为与Rails不同)
  • 仅针对同步通话
  • 写入同一会话

当我进行异步调用时,用async_sinatra代码编写的会话不会被推送到客户端计算机。我怀疑其中有两件事正在发生:

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

  • 标题被发送到客户端,但Rails立即发送另一个,指示客户端写入cookie在其session变量中存储的内容,覆盖西纳特拉写的是什么。

无论哪种方式,我都想在Sinatra和Rails中获得简单的会话功能。我正在做错的解释也很好:)

代码的完整工作副本是on github,但我相信此问题特别在此代码中:

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

编辑7/15

更改Github上的代码以包含Async-Rack。 Async-sinatra可以在与Rails共享时写入会话。比较mastersegmented_sessions分支的行为差异。 (或在master分支上,将use ActionDispatch::Session::CookieStore更改为enable :sessions

1 个答案:

答案 0 :(得分:1)

这是因为async_sinatra默认使用throw :async,有效地跳过会话中间件逻辑来存储东西。您可以像这样覆盖async_response

helpers do
  def async_response
    [-1, {}, []]
  end
end