public
Fork of markbates/mack
Description: A Ruby web application framework
Homepage: http://www.mackframework.com
Clone URL: git://github.com/juretta/mack.git
Search Repo:
mack / lib / mack.rb
100644 133 lines (122 sloc) 4.65 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require File.join(File.dirname(__FILE__), "initialization", "initializer")
 
module Mack
  # This is the heart and soul of the Mack framework! This class interfaces with the Rack framework.
  # It handles all the dispatching back and forth between the Rack framework and a Mack application.
  class Runner
    include Mack::Routes::Urls
    
    attr_reader :response # :nodoc:
    attr_reader :request # :nodoc:
    attr_reader :cookies # :nodoc:
    # This method needs to be defined as part of the Rack framework. As is noted for the Mack::Runner
    # class, this is where the center of the Mack framework lies.
    def call(env)
      # pp env
      begin
        setup(env) do
          begin
            route = Mack::Routes::RouteMap.instance.get_route_from_request(self.request)
            if route[:redirect_to]
              # because the route is specified to be a redirect, let's do that:
              redirect_to(route)
            else
              # let's handle a normal request:
              c = "#{route[:controller].to_s.camelcase}Controller".constantize.new(self.request, self.response, self.cookies)
              self.response.controller = c
              self.response.write(c.run)
            end
          rescue Mack::Errors::ResourceNotFound, Mack::Errors::UndefinedRoute => e
            return try_to_find_resource(env, self.request.path_info, e)
          end
        end # setup
      rescue Exception => e
        MACK_DEFAULT_LOGGER.error(e)
        raise e
      end
    end
    
    private
    def log_request
      s_time = Time.now
      x = yield
      e_time = Time.now
      p_time = e_time - s_time
      if app_config.log.detailed_requests
        msg = "\n\t[#{@request.request_method.upcase}] '#{@request.path_info}'\n"
        msg << "\tSession ID: #{@request.session.id}\n"
        msg << "\tParameters: #{@request.all_params.inspect}\n"
        msg << "\tCompleted in #{p_time} (#{(1 / p_time).round} reqs/sec) | #{@response.status} [#{@request.full_host}]"
      else
        msg = "[#{@request.request_method.upcase}] '#{@request.path_info}' (#{p_time})"
      end
      MACK_DEFAULT_LOGGER.info(msg)
      x
    end
    
    # Setup the request, response, cookies, session, etc...
    # yield up, and then clean things up afterwards.
    def setup(env)
      exception = nil
      log_request do
        @request = Mack::Request.new(env)
        @response = Mack::Response.new
        @cookies = Mack::CookieJar.new(self.request, self.response)
        session do
          begin
            yield
          rescue Exception => e
            exception = e
          end
        end
        return self.response.finish unless exception
      end
      raise exception if exception
    end
    
    def session
      sess_id = self.cookies[app_config.mack.session_id]
      unless sess_id
        sess_id = create_new_session
      else
        sess = Cachetastic::Caches::MackSessionCache.get(sess_id)
        if sess
          self.request.session = sess
        else
          # we couldn't find it in the store, so we need to create it:
          sess_id = create_new_session
        end
      end
 
      yield
      
      Cachetastic::Caches::MackSessionCache.set(sess_id, self.request.session)
    end
    
    def create_new_session
      id = String.randomize(40).downcase
      self.cookies[app_config.mack.session_id] = {:value => id, :expires => nil}
      sess = Mack::Session.new(id)
      self.request.session = sess
      Cachetastic::Caches::MackSessionCache.set(id, sess)
      id
    end
    
    def try_to_find_resource(env, path_info, exception)
      # we can't find a route for this, so let's try and see if it's in the public directory:
      if File.extname(path_info).blank?
        path_info << ".html"
      end
      if File.exists?(File.join(MACK_PUBLIC, path_info))
        return Rack::File.new(File.join(MACK_PUBLIC)).call(env)
      else
        raise exception
      end
    end
    
    # This will redirect the request to the specified url. A default status of
    # 302, Moved Temporarily, is set if no status is specified. A simple HTML
    # page is rendered in case the redirect does not occur.
    def redirect_to(route)
      status = route[:status] || 302
      url = route[:redirect_to]
      options = self.request.all_params
      options.merge!(route)
      options - [:controller, :action, :redirect_to, :method, :status, :format]
      url = url_for_pattern(url, options)
      self.response.status = status
      self.response[:location] = url
      self.response.write(redirect_html(self.request.path_info, url, status))
    end
    
  end
end