2

我正在尝试在测试和生产中运行我的 Ruby Sinatra 应用程序。这是主要课程:

class Main < Sinatra::Application

  helpers Sinatra::ContentFor
  helpers Sinatra::Partials
  helpers Sinatra::Auth

  use Rack::Session::Cookie, :secret => 'supersecret' , :expire_after => 360000

  set :environment, :production

  configure :development do
    enable :sessions, :logging, :dump_errors, :inline_templates
    enable :methodoverride
    set :root, $_APP_PATH
    set :static, true
    logger = Logger.new($stdout)
  end

  configure :production do
    enable :logging, :dump_errors, :inline_templates
    enable :methodoverride
    set :root, $_APP_PATH
    set :static, true
    logger = Logger.new($stdout)
  end

  get "/2configure" do
    haml :'2configure'
  end

end

这适用于set :environment, :development,但在“测试”和“生产”中会出现以下错误:

!! Unexpected error while processing request: undefined method `bytesize' for nil:NilClass

这是堆栈跟踪的顶部:

NoMethodError - undefined method `bytesize' for nil:NilClass:
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/utils.rb:291:in `bytesize'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/utils.rb:351:in `secure_compare'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/cookie.rb:115:in `unpacked_cookie_data'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/cookie.rb:105:in `extract_session_id'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:43:in `load_session_id!'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:32:in `[]'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:252:in `current_session_id'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:258:in `session_exists?'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:104:in `exists?'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:114:in `load_for_read!'
    /home/id833541/.rvm/gems/ruby-1.9.3-p392/gems/rack-1.3.10/lib/rack/session/abstract/id.rb:59:in `[]'

我几乎可以肯定这与会话有关。出于某种原因,在 Sinatra 中正确处理直肠是一种痛苦。我之前遇到过这个问题,但后来我通过使用enable :sessions. 现在即使这样也行不通了。

我已经确认访问会话时发生错误。在 HAML 文件中,我有:

%p="Welcome #{session[:full_name]}"

第一次是空的。但这应该给出错误吗?

任何请求都会发生这种情况,即使在我不尝试访问session对象但没有堆栈跟踪的请求中也是如此。

我正在使用瘦网络服务器。

4

2 回答 2

3

我相信这是因为你也use Rack::Session::Cookieenable :sessions。使用一个或另一个(我不知道为什么两者都不起作用,只是它是一个或另一个)。

顺便说一句,您是否尝试过使用https://rubygems.org/gems/encrypted_cookie而不是 Cookie?它更安全。


快速附录:我注意到您继承自Sinatra::Application. 如果您要继承以制作模块化应用程序,那么:

require 'sinatra/base'

class Main < Sinatra::Base

如果您想将其用作经典应用程序,那么它只是:

require 'sinatra'

# no `class` statement

get "/blah" do # etc

除了评论:

如果您使用的是 rackup 文件和 Rack 中间件,那么这就是我构建应用程序的方式:

root_of_project/
  config.ru        # This is just to start up the app via `rackup`.
  app/             # This will be the `root` setting in Sinatra
    config.rb      # This is where the logic of the Rack app lives.
    main.rb        # This is where your main Sinatra app lives
    models/
    views/
      2configure.haml
    public/

配置.ru

require 'rubygems'
require 'bundler'
Bundler.setup(:default) # and anything else you want added in

root = File.expand_path File.dirname(__FILE__)
require File.join( root , "./app/config.rb" )

map "/" do
  run MY_APP_NAMESPACE.app
end

应用程序/config.rb

require_relative "./main.rb" # Sinatra app

module MY_APP_NAMESPACE

  require 'encrypted_cookie'
  # standard cookie settings
  COOKIE_SETTINGS = {
    :path => "/",
    :expire_after => 86400, # In seconds, 1 day
    :secret => ENV["COOKIE_KEY"],  # I load this into the server's environment.
    :httponly => true
  }

  # This gets called in the config.ru. Doing it this way
  # makes it easy to include in specs.
  def self.app
    Rack::Builder.app do
      logger = Logger.new($stdout)


      cookie_settings = COOKIE_SETTINGS
      # more security if in production
      cookie_settings.merge!( :secure => true ) if ENV["RACK_ENV"] == "production"

      # AES encryption of cookies
      use Rack::Session::EncryptedCookie, cookie_settings

      # any other Rack middleware I put here.

      run Main
    end
  end
end # module

应用程序/main.rb

require 'sinatra/base'

module MY_APP_NAMESPACE
  class Main < Sinatra::Base

    helpers Sinatra::ContentFor
    helpers Sinatra::Partials
    helpers Sinatra::Auth

    # no need for this here
    # use Rack::Session::Cookie, :secret => 'supersecret' , :expire_after => 360000

    # no need for this
    # set :environment, :production

    configure :development do
      #enable :sessions,  # no need
      enable :logging, :dump_errors, :inline_templates
      enable :methodoverride
      # Sinatra will work this out
      # set :root, $_APP_PATH
      # set :static, true # no need if you have a public directory
    end

    configure :production do
      enable :dump_errors, :inline_templates
      enable :methodoverride
      # set :root, $_APP_PATH
      # set :static, true  
      # logger = Logger.new($stdout) # no need for this, as far as I remember
      # see http://www.sinatrarb.com/intro#Logging
    end

    get "/2configure" do
      haml :'2configure'
    end

  end

希望这会给你一些尝试的想法。

于 2013-05-07T11:46:27.150 回答
1

显然问题出在Rack::Session::Cookie某个地方。我现在可以改用以下内容:

use Rack::Session::Pool, :secret => 'super secret' , :expire_after => 360000

Rack::Session::Cookie但是我的应用程序稍后将与当前使用的另一个应用程序集成。

我仍然想知道为什么Cookie不起作用。

于 2013-05-07T11:36:03.093 回答