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

发布于 2024-11-19 23:49:21 字数 1994 浏览 4 评论 0 原文

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

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

当我进行异步调用时,以 async_sinatra 代码编写的会话不会被推送到客户端计算机。我怀疑发生了以下两件事之一:

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

  • 标头被发送到客户端,但Rails立即发送另一个标头,指示客户端将Rails存储在其session变量中的内容写入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

编辑 7/15

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

I have a Sinatra class in a Rails project. It uses eventmachine and async_sinatra to make asynchronous calls to external sites. I'd like to write to a session object (ideally, the same one that Rails is using), but so far I can only:

  • write to a separate session object from Rails' (by default, Sinatra names its session something different from Rails)
  • write to the same session for synchronous calls only

When I make asynchronous calls, sessions written in the async_sinatra code don't get pushed out to the client machine. I suspect one of two things is happening:

  • The header has already been sent to the client and the local variable storing the session (in Sinatra) will be flushed out at the end of the action. The client would never see a request from the server to save this data to a cookie.

  • The header is being sent to the client, but Rails immediate sends another, instructing the client to write to the cookie what Rails has stored in its session variable, overwriting what Sinatra wrote.

Either way, I'd like to just get simple session functionality in both Sinatra and Rails. An explanation of what I'm doing wrong would also be nice :)

A full working copy of the code is on github, but I believe the problem is specifically in this code:

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

EDIT 7/15:

Changed code on Github to include Async-Rack. Async-sinatra can write to sessions when they are not shared with Rails. Compare the master and segmented_sessions branches for behavior difference. (Or on the master branch, change use ActionDispatch::Session::CookieStore to enable :sessions)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

简单爱 2024-11-26 23:49:21

这是因为 async_sinatra 默认情况下使用 throw :async,有效地跳过了用于存储内容的会话中间件逻辑。您可以像这样覆盖 async_response那:

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

This is because async_sinatra uses throw :async by default, effectively skipping the session middleware logic for storing stuff. You could override async_response like that:

helpers do
  def async_response
    [-1, {}, []]
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文