class SBSM::RackInterface

Constants

SESSION_ID

Attributes

session[RW]
session_store[R]
unknown_user[R]

Public Class Methods

new(app:, validator: nil, trans_handler: nil, session_class: nil, persistence_layer: nil, unknown_user: nil, cookie_name: nil, multi_threaded: nil ) click to toggle source

Base class for a SBSM based WebRick HTTP server

  • offer a call(env) method form handling the WebRick requests

This is all what is needed to be compatible with WebRick

optional arguments

  • app - A Ruby class used by the session

  • validator - A Ruby class overriding the SBSM::Validator class

  • trans_handler - A Ruby class overriding the SBSM::TransHandler class

  • session_class - A Ruby class overriding the SBSM::Session class

  • unknown_user - A Ruby class overriding the SBSM::UnknownUser class

  • persistence_layer - Persistence Layer to use

  • cookie_name - The cookie to save persistent user data

  • multi_threaded - Allow multi_threaded SBSM (default is false)

Examples

Look at steinwies.ch

# File lib/sbsm/app.rb, line 69
def initialize(app:,
               validator: nil,
               trans_handler:  nil,
               session_class: nil,
               persistence_layer: nil,
               unknown_user: nil,
               cookie_name: nil,
               multi_threaded: nil
             )
  @@last_session = nil
  @app = app
  SBSM.info "initialize validator #{validator} th #{trans_handler} cookie #{cookie_name} session #{session_class} app #{app} multi_threaded #{multi_threaded}"
  @session_store = SessionStore.new(app: app,
                                    persistence_layer: persistence_layer,
                                    trans_handler: trans_handler,
                                    session_class: session_class,
                                    cookie_name: cookie_name,
                                    unknown_user: unknown_user,
                                    validator: validator,
                                    multi_threaded: multi_threaded)
  @unknown_user = unknown_user
end

Private Class Methods

last_session() click to toggle source
# File lib/sbsm/app.rb, line 168
def self.last_session  # for unit tests only
  @@last_session
end

Public Instance Methods

call(env) click to toggle source
# File lib/sbsm/app.rb, line 96
def call(env) ## mimick sbsm/lib/app.rb
  request = Rack::Request.new(env)
  response = Rack::Response.new
  if request.cookies[SESSION_ID] && request.cookies[SESSION_ID].length > 1
    session_id = request.cookies[SESSION_ID]
  else
    session_id = rand((2**(0.size * 8 -2) -1)*10240000000000).to_s(16)
  end
  if '/'.eql?(request.path)
    file_name = File.expand_path(File.join('doc', 'index.html'))
  else
    file_name = File.expand_path(File.join('doc', request.path))
  end
  if File.file?(file_name)
    if File.extname(file_name).length > 0 && (mime_info = MimeMagic.by_extension(File.extname(file_name)))
      mime_type = mime_info.type
    else
      mime_type = MimeMagic.by_path(file_name)
    end
    mime_type ||= 'text/plain'
    SBSM.debug "file_name is #{file_name} checkin base #{File.basename(file_name)} MIME #{mime_type}"
    response.set_header('Content-Type', mime_type)
    response.write(File.open(file_name, File::RDONLY){|file| file.read})
    return response.finish
  end

  return [400, {}, []] if /favicon.ico/i.match(request.path)
  Thread.current.thread_variable_set(:session, @session_store[session_id])
  session = Thread.current.thread_variable_get(:session)
  SBSM.debug "starting session_id #{session_id}  session #{session.class} #{request.path}: cookies #{@cookie_name} are #{request.cookies} @cgi #{@cgi.class}"
  res = session.process_rack(rack_request: request)
  thru = session.get_passthru
  if thru.size > 0
    begin
      file_name = thru.first
      raise Errno::ENOENT unless File.exist?(file_name)
      response.set_header('Content-Type', MimeMagic.by_extension(File.extname(file_name)).type)
      response.headers['Content-Disposition'] = "#{thru.last}; filename=#{File.basename(file_name)}"
      response.headers['Content-Length'] =  File.size(file_name).to_s
      response.write(File.open(file_name, File::RDONLY){|file| file.read})
    rescue Errno::ENOENT, IOError => err
      error_msg = "#{file_name} Not found\n"
      SBSM.error("#{err.message} #{thru.first} => #{error_msg}")
      return [404, {'Content-Type' => 'text/html', 'Content-Length' => error_msg.size.to_s}, [error_msg]]
    end
  else
    response.write res unless request.request_method.eql?('HEAD')
    response.headers['Content-Type'] ||= 'text/html; charset=utf-8'
    response.headers.merge!(session.http_headers)
  end

  if (result = response.headers.find { |k,v| /status/i.match(k) })
    response.status = result.last.to_i
    response.headers.delete(result.first)
  end
  response.set_cookie(session.persistent_cookie_name,
                      { :value    => session.cookie_pairs,
                        :path     => "/",
                        :expires  => (Time.now + (60 * 60 * 24 * 365 * 10))})
  response.set_cookie(SESSION_ID, { :value => session_id, :path => '/' ,  :expires => (Time.now + (60 * 60 * 24 * 365 * 10)) })
  # bad idea to reset rack_request if we need more page
  @@last_session = session
  if response.headers['Set-Cookie'].to_s.index(session_id)
    SBSM.debug "finish session_id.1 #{session_id}: matches response.headers['Set-Cookie'] #{response.headers['Set-Cookie']}"
  else
    SBSM.debug "finish session_id.2 #{session_id}: headers #{response.headers}"
  end
  response.status = 302 if response.headers['Location']
  response.finish
end
last_session() click to toggle source
# File lib/sbsm/app.rb, line 92
def last_session
  @@last_session
end