pancake 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.textile +95 -0
- data/Rakefile +56 -0
- data/TODO +17 -0
- data/bin/jeweler +19 -0
- data/bin/pancake-gen +17 -0
- data/bin/rubyforge +19 -0
- data/lib/pancake/bootloaders.rb +180 -0
- data/lib/pancake/configuration.rb +145 -0
- data/lib/pancake/constants.rb +5 -0
- data/lib/pancake/core_ext/class.rb +44 -0
- data/lib/pancake/core_ext/object.rb +22 -0
- data/lib/pancake/core_ext/symbol.rb +15 -0
- data/lib/pancake/defaults/configuration.rb +22 -0
- data/lib/pancake/defaults/middlewares.rb +1 -0
- data/lib/pancake/errors.rb +61 -0
- data/lib/pancake/generators/base.rb +12 -0
- data/lib/pancake/generators/micro_generator.rb +17 -0
- data/lib/pancake/generators/short_generator.rb +17 -0
- data/lib/pancake/generators/stack_generator.rb +17 -0
- data/lib/pancake/generators/templates/common/dotgitignore +22 -0
- data/lib/pancake/generators/templates/common/dothtaccess +17 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/%stack_name%.rb.tt +8 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/config.ru.tt +12 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/micro/%stack_name%/views/root.html.haml +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/LICENSE.tt +20 -0
- data/lib/pancake/generators/templates/short/%stack_name%/README.tt +7 -0
- data/lib/pancake/generators/templates/short/%stack_name%/Rakefile.tt +50 -0
- data/lib/pancake/generators/templates/short/%stack_name%/VERSION.tt +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/%stack_name%.rb.tt +6 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config.ru.tt +10 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/mounts/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/views/root.html.haml +2 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%.rb.tt +5 -0
- data/lib/pancake/generators/templates/short/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/spec/%stack_name%_spec.rb.tt +7 -0
- data/lib/pancake/generators/templates/short/%stack_name%/spec/spec_helper.rb.tt +9 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/LICENSE.tt +20 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/README.tt +7 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/Rakefile.tt +50 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/VERSION.tt +1 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/environments/development.rb.tt +18 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/environments/production.rb.tt +18 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/router.rb.tt +6 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config.ru.tt +12 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/gems/cache/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/mounts/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%.rb.tt +3 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/spec/%stack_name%_spec.rb.tt +7 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/spec/spec_helper.rb.tt +9 -0
- data/lib/pancake/generators.rb +8 -0
- data/lib/pancake/hooks/inheritable_inner_classes.rb +60 -0
- data/lib/pancake/hooks/on_inherit.rb +34 -0
- data/lib/pancake/logger.rb +200 -0
- data/lib/pancake/master.rb +123 -0
- data/lib/pancake/middleware.rb +347 -0
- data/lib/pancake/middlewares/logger.rb +16 -0
- data/lib/pancake/middlewares/static.rb +38 -0
- data/lib/pancake/mime_types.rb +265 -0
- data/lib/pancake/mixins/publish/action_options.rb +104 -0
- data/lib/pancake/mixins/publish.rb +125 -0
- data/lib/pancake/mixins/render/render.rb +168 -0
- data/lib/pancake/mixins/render/template.rb +23 -0
- data/lib/pancake/mixins/render/view_context.rb +21 -0
- data/lib/pancake/mixins/render.rb +109 -0
- data/lib/pancake/mixins/request_helper.rb +100 -0
- data/lib/pancake/mixins/stack_helper.rb +46 -0
- data/lib/pancake/mixins/url.rb +10 -0
- data/lib/pancake/paths.rb +218 -0
- data/lib/pancake/router.rb +99 -0
- data/lib/pancake/stack/app.rb +10 -0
- data/lib/pancake/stack/bootloader.rb +79 -0
- data/lib/pancake/stack/configuration.rb +44 -0
- data/lib/pancake/stack/middleware.rb +0 -0
- data/lib/pancake/stack/router.rb +21 -0
- data/lib/pancake/stack/stack.rb +66 -0
- data/lib/pancake/stacks/short/bootloaders.rb +13 -0
- data/lib/pancake/stacks/short/controller.rb +116 -0
- data/lib/pancake/stacks/short/default/views/base.html.haml +5 -0
- data/lib/pancake/stacks/short/stack.rb +187 -0
- data/lib/pancake/stacks/short.rb +3 -0
- data/lib/pancake.rb +58 -0
- data/spec/helpers/helpers.rb +20 -0
- data/spec/helpers/matchers.rb +25 -0
- data/spec/pancake/bootloaders_spec.rb +109 -0
- data/spec/pancake/configuration_spec.rb +177 -0
- data/spec/pancake/constants_spec.rb +7 -0
- data/spec/pancake/defaults/configuration_spec.rb +58 -0
- data/spec/pancake/fixtures/foo_stack/pancake.init +0 -0
- data/spec/pancake/fixtures/middlewares/other_public/two.html +1 -0
- data/spec/pancake/fixtures/middlewares/public/foo#bar.html +1 -0
- data/spec/pancake/fixtures/middlewares/public/one.html +1 -0
- data/spec/pancake/fixtures/paths/controllers/controller1.rb +0 -0
- data/spec/pancake/fixtures/paths/controllers/controller2.rb +0 -0
- data/spec/pancake/fixtures/paths/controllers/controller3.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model1.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model2.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model3.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/controllers/controller1.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/models/model3.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view1.erb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view1.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view2.erb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view2.haml +0 -0
- data/spec/pancake/fixtures/render_templates/context_template.html.erb +2 -0
- data/spec/pancake/fixtures/render_templates/erb_template.html.erb +1 -0
- data/spec/pancake/fixtures/render_templates/erb_template.json.erb +1 -0
- data/spec/pancake/fixtures/render_templates/haml_template.html.haml +1 -0
- data/spec/pancake/fixtures/render_templates/haml_template.xml.haml +1 -0
- data/spec/pancake/fixtures/render_templates/templates/context.erb +2 -0
- data/spec/pancake/fixtures/render_templates/view_context/capture_erb.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/capture_haml.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/concat_erb.erb +2 -0
- data/spec/pancake/fixtures/render_templates/view_context/concat_haml.haml +2 -0
- data/spec/pancake/fixtures/render_templates/view_context/context.erb +3 -0
- data/spec/pancake/fixtures/render_templates/view_context/context2.erb +3 -0
- data/spec/pancake/fixtures/render_templates/view_context/helper_methods.erb +3 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_erb_from_haml.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_erb_level_0.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_erb_level_1.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_haml_from_erb.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_haml_level_0.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/inherited_haml_level_1.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/nested_content_level_0.haml +6 -0
- data/spec/pancake/fixtures/render_templates/view_context/nested_content_level_1.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/nested_inner.erb +1 -0
- data/spec/pancake/fixtures/render_templates/view_context/nested_outer.erb +3 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_erb_from_erb_0.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_erb_from_erb_1.erb +6 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_erb_from_haml_0.erb +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_erb_from_haml_1.erb +6 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_haml_from_erb_0.haml +4 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_haml_from_erb_1.haml +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_haml_from_haml_0.haml +5 -0
- data/spec/pancake/fixtures/render_templates/view_context/super_haml_from_haml_1.haml +5 -0
- data/spec/pancake/fixtures/stacks/short/foobar/other_root/views/base.html.haml +4 -0
- data/spec/pancake/fixtures/stacks/short/foobar/views/basic.html.haml +1 -0
- data/spec/pancake/fixtures/stacks/short/foobar/views/inherited_from_base.html.haml +5 -0
- data/spec/pancake/hooks/on_inherit_spec.rb +65 -0
- data/spec/pancake/inheritance_spec.rb +100 -0
- data/spec/pancake/middleware_spec.rb +401 -0
- data/spec/pancake/middlewares/logger_spec.rb +29 -0
- data/spec/pancake/middlewares/static_spec.rb +83 -0
- data/spec/pancake/mime_types_spec.rb +234 -0
- data/spec/pancake/mixins/publish_spec.rb +94 -0
- data/spec/pancake/mixins/render/template_spec.rb +69 -0
- data/spec/pancake/mixins/render/view_context_spec.rb +248 -0
- data/spec/pancake/mixins/render_spec.rb +56 -0
- data/spec/pancake/mixins/request_helper_spec.rb +27 -0
- data/spec/pancake/mixins/stack_helper_spec.rb +46 -0
- data/spec/pancake/pancake_spec.rb +90 -0
- data/spec/pancake/paths_spec.rb +210 -0
- data/spec/pancake/stack/app_spec.rb +28 -0
- data/spec/pancake/stack/bootloader_spec.rb +41 -0
- data/spec/pancake/stack/middleware_spec.rb +0 -0
- data/spec/pancake/stack/router_spec.rb +282 -0
- data/spec/pancake/stack/stack_configuration_spec.rb +101 -0
- data/spec/pancake/stack/stack_spec.rb +60 -0
- data/spec/pancake/stacks/short/controller_spec.rb +322 -0
- data/spec/pancake/stacks/short/middlewares_spec.rb +22 -0
- data/spec/pancake/stacks/short/router_spec.rb +136 -0
- data/spec/pancake/stacks/short/stack_spec.rb +64 -0
- data/spec/spec_helper.rb +23 -0
- metadata +294 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Pancake::Logger == Merb::Logger
|
|
2
|
+
class Pancake::Logger < Extlib::Logger
|
|
3
|
+
# :api: public
|
|
4
|
+
def verbose!(message, level = :warn)
|
|
5
|
+
send("#{level}!", message) if Pancake.configuration.verbose_logging
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# :api: public
|
|
9
|
+
def verbose(message, level = :warn)
|
|
10
|
+
send(level, message) if Pancake.configuration.verbose_logging
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# require "time" # httpdate
|
|
15
|
+
# ==== Public Pancake Logger API
|
|
16
|
+
#
|
|
17
|
+
# To replace an existing logger with a new one:
|
|
18
|
+
# Pancake::Logger.set_log(log{String, IO},level{Symbol, String})
|
|
19
|
+
#
|
|
20
|
+
# Available logging levels are
|
|
21
|
+
# Pancake::Logger::{ Fatal, Error, Warn, Info, Debug }
|
|
22
|
+
#
|
|
23
|
+
# Logging via:
|
|
24
|
+
# Pancake.logger.fatal(message<String>,&block)
|
|
25
|
+
# Pancake.logger.error(message<String>,&block)
|
|
26
|
+
# Pancake.logger.warn(message<String>,&block)
|
|
27
|
+
# Pancake.logger.info(message<String>,&block)
|
|
28
|
+
# Pancake.logger.debug(message<String>,&block)
|
|
29
|
+
#
|
|
30
|
+
# Logging with autoflush:
|
|
31
|
+
# Pancake.logger.fatal!(message<String>,&block)
|
|
32
|
+
# Pancake.logger.error!(message<String>,&block)
|
|
33
|
+
# Pancake.logger.warn!(message<String>,&block)
|
|
34
|
+
# Pancake.logger.info!(message<String>,&block)
|
|
35
|
+
# Pancake.logger.debug!(message<String>,&block)
|
|
36
|
+
#
|
|
37
|
+
# Flush the buffer to
|
|
38
|
+
# Pancake.logger.flush
|
|
39
|
+
#
|
|
40
|
+
# Remove the current log object
|
|
41
|
+
# Pancake.logger.close
|
|
42
|
+
#
|
|
43
|
+
# ==== Private Pancake Logger API
|
|
44
|
+
#
|
|
45
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
46
|
+
# Pancake::Logger.new(log{String, IO},level{Symbol, String})
|
|
47
|
+
module Pancake
|
|
48
|
+
|
|
49
|
+
class Logger
|
|
50
|
+
|
|
51
|
+
attr_accessor :level
|
|
52
|
+
attr_accessor :delimiter
|
|
53
|
+
attr_accessor :auto_flush
|
|
54
|
+
attr_reader :buffer
|
|
55
|
+
attr_reader :log
|
|
56
|
+
attr_reader :init_args
|
|
57
|
+
|
|
58
|
+
# ==== Notes
|
|
59
|
+
# Ruby (standard) logger levels:
|
|
60
|
+
# :fatal:: An unhandleable error that results in a program crash
|
|
61
|
+
# :error:: A handleable error condition
|
|
62
|
+
# :warn:: A warning
|
|
63
|
+
# :info:: generic (useful) information about system operation
|
|
64
|
+
# :debug:: low-level information for developers
|
|
65
|
+
Levels = Mash.new({
|
|
66
|
+
:fatal => 7,
|
|
67
|
+
:error => 6,
|
|
68
|
+
:warn => 4,
|
|
69
|
+
:info => 3,
|
|
70
|
+
:debug => 0
|
|
71
|
+
}) unless const_defined?(:Levels)
|
|
72
|
+
|
|
73
|
+
@@mutex = {}
|
|
74
|
+
|
|
75
|
+
public
|
|
76
|
+
|
|
77
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
78
|
+
#
|
|
79
|
+
# ==== Parameters
|
|
80
|
+
# *args:: Arguments to create the log from. See set_logs for specifics.
|
|
81
|
+
def initialize(*args)
|
|
82
|
+
set_log(*args)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Replaces an existing logger with a new one.
|
|
86
|
+
#
|
|
87
|
+
# ==== Parameters
|
|
88
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
|
89
|
+
# log_level<~to_sym>::
|
|
90
|
+
# The log level from, e.g. :fatal or :info. Defaults to :error in the
|
|
91
|
+
# production environment and :debug otherwise.
|
|
92
|
+
# delimiter<String>::
|
|
93
|
+
# Delimiter to use between message sections. Defaults to " ~ ".
|
|
94
|
+
# auto_flush<Boolean>::
|
|
95
|
+
# Whether the log should automatically flush after new messages are
|
|
96
|
+
# added. Defaults to false.
|
|
97
|
+
def set_log(stream = Pancake.configuration.log_stream,
|
|
98
|
+
log_level = Pancake.configuration.log_level,
|
|
99
|
+
delimiter = Pancake.configuration.log_delimiter,
|
|
100
|
+
auto_flush = Pancake.configuration.log_auto_flush)
|
|
101
|
+
|
|
102
|
+
@buffer = []
|
|
103
|
+
@delimiter = delimiter
|
|
104
|
+
@auto_flush = auto_flush
|
|
105
|
+
|
|
106
|
+
if Levels[log_level]
|
|
107
|
+
@level = Levels[log_level]
|
|
108
|
+
else
|
|
109
|
+
@level = log_level
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
@log = stream
|
|
113
|
+
@log.sync = true
|
|
114
|
+
@mutex = (@@mutex[@log] ||= Mutex.new)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Flush the entire buffer to the log object.
|
|
118
|
+
def flush
|
|
119
|
+
return unless @buffer.size > 0
|
|
120
|
+
@mutex.synchronize do
|
|
121
|
+
@log.write(@buffer.slice!(0..-1).join(''))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Close and remove the current log object.
|
|
126
|
+
def close
|
|
127
|
+
flush
|
|
128
|
+
@log.close if @log.respond_to?(:close) && !@log.tty?
|
|
129
|
+
@log = nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Appends a message to the log. The methods yield to an optional block and
|
|
133
|
+
# the output of this block will be appended to the message.
|
|
134
|
+
#
|
|
135
|
+
# ==== Parameters
|
|
136
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
137
|
+
#
|
|
138
|
+
# ==== Returns
|
|
139
|
+
# String:: The resulting message added to the log file.
|
|
140
|
+
def <<(string = nil)
|
|
141
|
+
message = ""
|
|
142
|
+
message << delimiter
|
|
143
|
+
message << string if string
|
|
144
|
+
message << "\n" unless message[-1] == ?\n
|
|
145
|
+
@buffer << message
|
|
146
|
+
flush if @auto_flush
|
|
147
|
+
|
|
148
|
+
message
|
|
149
|
+
end
|
|
150
|
+
alias :push :<<
|
|
151
|
+
|
|
152
|
+
# Generate the logging methods for Pancake.logger for each log level.
|
|
153
|
+
Levels.each_pair do |name, number|
|
|
154
|
+
class_eval <<-LEVELMETHODS, __FILE__, __LINE__
|
|
155
|
+
|
|
156
|
+
# Appends a message to the log if the log level is at least as high as
|
|
157
|
+
# the log level of the logger.
|
|
158
|
+
#
|
|
159
|
+
# ==== Parameters
|
|
160
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
161
|
+
#
|
|
162
|
+
# ==== Returns
|
|
163
|
+
# self:: The logger object for chaining.
|
|
164
|
+
def #{name}(message = nil)
|
|
165
|
+
if #{number} >= level
|
|
166
|
+
message = block_given? ? yield : message
|
|
167
|
+
self << message if #{number} >= level
|
|
168
|
+
end
|
|
169
|
+
self
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Appends a message to the log if the log level is at least as high as
|
|
173
|
+
# the log level of the logger. The bang! version of the method also auto
|
|
174
|
+
# flushes the log buffer to disk.
|
|
175
|
+
#
|
|
176
|
+
# ==== Parameters
|
|
177
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
178
|
+
#
|
|
179
|
+
# ==== Returns
|
|
180
|
+
# self:: The logger object for chaining.
|
|
181
|
+
def #{name}!(message = nil)
|
|
182
|
+
if #{number} >= level
|
|
183
|
+
message = block_given? ? yield : message
|
|
184
|
+
self << message if #{number} >= level
|
|
185
|
+
flush if #{number} >= level
|
|
186
|
+
end
|
|
187
|
+
self
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# ==== Returns
|
|
191
|
+
# Boolean:: True if this level will be logged by this logger.
|
|
192
|
+
def #{name}?
|
|
193
|
+
#{number} >= level
|
|
194
|
+
end
|
|
195
|
+
LEVELMETHODS
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
# A simple rack application
|
|
3
|
+
OK_APP = lambda{|env| Rack::Response.new("OK", 200, {"Content-Type" => "text/plain"}).finish}
|
|
4
|
+
MISSING_APP = lambda{|env| Rack::Response.new("NOT FOUND", 404, {"Content-Type" => "text/plain"}).finish}
|
|
5
|
+
|
|
6
|
+
extend Middleware
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
attr_accessor :root
|
|
10
|
+
|
|
11
|
+
# Start Pancake. This provides a full pancake stack to use inside a rack application
|
|
12
|
+
#
|
|
13
|
+
# @param [Hash] opts
|
|
14
|
+
# @option opts [String] :root The root of the pancake stack
|
|
15
|
+
#
|
|
16
|
+
# @example Starting a pancake stack
|
|
17
|
+
# Pancake.start(:root => "/path/to/root"){ MyApp # App to use}
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
20
|
+
# @author Daniel Neighman
|
|
21
|
+
def start(opts, &block)
|
|
22
|
+
raise "You must specify a root directory for pancake" unless opts[:root]
|
|
23
|
+
self.root = opts[:root]
|
|
24
|
+
|
|
25
|
+
# Build Pancake
|
|
26
|
+
the_app = instance_eval(&block)
|
|
27
|
+
Pancake::Middleware.build(the_app, middlewares)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Provides the environment for the currently running pancake
|
|
31
|
+
#
|
|
32
|
+
# @return [String] The currently running environment
|
|
33
|
+
# @api public
|
|
34
|
+
# @author Daniel Neighman
|
|
35
|
+
def env
|
|
36
|
+
ENV['RACK_ENV'] ||= "development"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A helper method to get the expanded directory name of a __FILE__
|
|
40
|
+
#
|
|
41
|
+
# @return [String] an expanded version of file
|
|
42
|
+
# @api public
|
|
43
|
+
# @author Daniel Neighman
|
|
44
|
+
def get_root(file, *args)
|
|
45
|
+
File.expand_path(File.join(File.dirname(file), *args))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Labels that specify what kind of stack you're intending on loading.
|
|
49
|
+
# This is a simliar concept to environments but it is in fact seperate conceptually.
|
|
50
|
+
#
|
|
51
|
+
# The reasoning is that you may want to use a particular stack type or types.
|
|
52
|
+
# By using stack labels, you can define middleware to be active.
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# Pancake.stack_labels == [:development, :demo]
|
|
56
|
+
#
|
|
57
|
+
# # This would activate middleware marked with :development or :demo or the implicit :any label
|
|
58
|
+
#
|
|
59
|
+
# @return [Array<Symbol>]
|
|
60
|
+
# An array of labels to activate
|
|
61
|
+
# The default is [:production]
|
|
62
|
+
# @see Pancake.stack_labels= to set the labels for this stack
|
|
63
|
+
# @see Pancake::Middleware#stack to see how to specify middleware to be active for the given labels
|
|
64
|
+
# @api public
|
|
65
|
+
# @author Daniel Neighman
|
|
66
|
+
def stack_labels
|
|
67
|
+
return @stack_labels unless @stack_labels.nil? || @stack_labels.empty?
|
|
68
|
+
self.stack_labels = [:production]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Sets the stack labels to activate the associated middleware
|
|
72
|
+
#
|
|
73
|
+
# @param [Array<Symbol>, Symbol] An array of labels or a single label, specifying the middlewares to activate
|
|
74
|
+
#
|
|
75
|
+
# @example
|
|
76
|
+
# Pancake.stack_labels = [:demo, :production]
|
|
77
|
+
#
|
|
78
|
+
# @see Pancake.stack_labels
|
|
79
|
+
# @see Pancake::Middleware#stack
|
|
80
|
+
# @api public
|
|
81
|
+
# @author Daniel Neighman
|
|
82
|
+
def stack_labels=(*labels)
|
|
83
|
+
@stack_labels = labels.flatten.compact
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def handle_errors!(*args)
|
|
87
|
+
@handle_errors = begin
|
|
88
|
+
if args.size > 1
|
|
89
|
+
args.flatten
|
|
90
|
+
else
|
|
91
|
+
args.first
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def handle_errors?
|
|
97
|
+
if @handle_errors.nil?
|
|
98
|
+
!(Pancake.env == "development")
|
|
99
|
+
else
|
|
100
|
+
case @handle_errors
|
|
101
|
+
when Array
|
|
102
|
+
@handle_errors.include?(Pancake.env)
|
|
103
|
+
when TrueClass, FalseClass
|
|
104
|
+
@handle_errors
|
|
105
|
+
when String
|
|
106
|
+
Pancake.env == @handle_errors
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def default_error_handling!
|
|
112
|
+
@handle_errors = nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def logger
|
|
116
|
+
@logger ||= Pancake::Logger.new
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def logger=(logr)
|
|
120
|
+
@logger = logr
|
|
121
|
+
end
|
|
122
|
+
end # self
|
|
123
|
+
end # Pancake
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
# Provides a mixin to use on any class to give it middleware management capabilities.
|
|
3
|
+
# This module provides a rich featureset for defining a middleware stack.
|
|
4
|
+
#
|
|
5
|
+
# Middlware can be set before, or after other middleware, can be tagged / named,
|
|
6
|
+
# and can be declared to only be active in certain types of stacks.
|
|
7
|
+
module Middleware
|
|
8
|
+
|
|
9
|
+
# When extending a base class with the Pancake::Middleware,
|
|
10
|
+
# an inner class StackMiddleware is setup on the base class.
|
|
11
|
+
# This inner class is where all the inforamation is stored on the stack to be defined
|
|
12
|
+
# The inner StackMiddleware class is also set to be inherited
|
|
13
|
+
# with the base class (and all children classes)
|
|
14
|
+
# So that each class gets its own copy and may maintain the base
|
|
15
|
+
# stack from the parent, but edit it in the child.
|
|
16
|
+
def self.extended(base)
|
|
17
|
+
base.class_eval <<-RUBY
|
|
18
|
+
class StackMiddleware < Pancake::Middleware::StackMiddleware; end
|
|
19
|
+
RUBY
|
|
20
|
+
if base.is_a?(Class)
|
|
21
|
+
base.inheritable_inner_classes :StackMiddleware
|
|
22
|
+
end
|
|
23
|
+
super
|
|
24
|
+
end # self.extended
|
|
25
|
+
|
|
26
|
+
# Build a middleware stack given an application and some middleware classes
|
|
27
|
+
#
|
|
28
|
+
# @param [Object] app a rack application to wrap in the middlware list
|
|
29
|
+
# @param [Array<StackMiddleware>] mwares an array of
|
|
30
|
+
# StackMiddleware instances where each instance
|
|
31
|
+
# defines a middleware to use in constructing the stack
|
|
32
|
+
#
|
|
33
|
+
# @example
|
|
34
|
+
# Pancake::Middleware.build(@app, [MWare_1, MWare_2])
|
|
35
|
+
# @return [Object]
|
|
36
|
+
# An application instance of the first middleware defined in the array
|
|
37
|
+
# The application should be an instance that conforms to Rack specifications
|
|
38
|
+
#
|
|
39
|
+
# @api public
|
|
40
|
+
# @since 0.1.0
|
|
41
|
+
# @author Daniel Neighman
|
|
42
|
+
def self.build(app, mwares)
|
|
43
|
+
mwares.reverse.inject(app) do |a, m|
|
|
44
|
+
m.middleware.new(a, *m.args, &m.block)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param [Array<Symbol>] labels An array of labels specifying the stack labels to use to build the middlware list
|
|
49
|
+
#
|
|
50
|
+
# @example
|
|
51
|
+
# MyApp.middlewares(:production) # provides all middlewares matching the :production label, or the implicit :any label
|
|
52
|
+
# MyApp.middlewares(:development, :demo) # provides all middlewares matching the :development or :demo or implicit :any label
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<StackMiddleware>]
|
|
55
|
+
# An array of middleware specifications in the order they should be used to wrap the application
|
|
56
|
+
#
|
|
57
|
+
# @see Pancake::Middleware::StackMiddleware
|
|
58
|
+
# @see Pancake.stack_labels for a decription of stack_labels
|
|
59
|
+
# @api public
|
|
60
|
+
# @since 0.1.0
|
|
61
|
+
# @author Daniel Neighman
|
|
62
|
+
def middlewares(*labels)
|
|
63
|
+
labels = labels.flatten
|
|
64
|
+
self::StackMiddleware.middlewares(*labels)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Useful for adding additional information into your middleware stack definition
|
|
68
|
+
#
|
|
69
|
+
# @param [Object] name
|
|
70
|
+
# The name of a given middleware. Each piece of middleware has a name in the stack.
|
|
71
|
+
# By naming middleware we can refer to it later, swap it out for a different class or even just remove it from the stack.
|
|
72
|
+
# @param [Hash] opts An options hash
|
|
73
|
+
# @option opts [Array<Symbol>] :labels ([:any])
|
|
74
|
+
# An array of symbols, or a straight symbol that defines what stacks this middleware sould be active in
|
|
75
|
+
# @option opts [Object] :before
|
|
76
|
+
# Sets this middlware to be run after the middleware named. Name is either the name given to the
|
|
77
|
+
# middleware stack, or the Middleware class itself.
|
|
78
|
+
# @option opts [Object] :after
|
|
79
|
+
# Sets this middleware to be run after the middleware name. Name is either the name given to the
|
|
80
|
+
# middleware stack or the Middleware class itself.
|
|
81
|
+
#
|
|
82
|
+
# @example Declaring un-named middleware via the stack
|
|
83
|
+
# MyClass.stack.use(MyMiddleware)
|
|
84
|
+
#
|
|
85
|
+
# This middleware will be named MyMiddleware, and can be specified with (:before | :after) => MyMiddleware
|
|
86
|
+
#
|
|
87
|
+
# @example Declaring a named middleware via the stack
|
|
88
|
+
# MyClass.stack(:foo).use(MyMiddleware)
|
|
89
|
+
#
|
|
90
|
+
# This middleware will be named :foo and can be specified with (:before | :after) => :foo
|
|
91
|
+
#
|
|
92
|
+
# @example Declaring a named middleware with a :before key
|
|
93
|
+
# MyClass.stack(:foo, :before => :bar).use(MyMiddleware)
|
|
94
|
+
#
|
|
95
|
+
# This middleware will be named :foo and will be run before the middleware named :bar
|
|
96
|
+
# If :bar is not run, :foo will not be run either
|
|
97
|
+
#
|
|
98
|
+
# @example Declaring a named middlware with an :after key
|
|
99
|
+
# MyClass.stack(:foo, :after => :bar).use(MyMiddleware)
|
|
100
|
+
#
|
|
101
|
+
# This middleware will be named :foo and will be run after the middleware named :bar
|
|
102
|
+
# If :bar is not run, :foo will not be run either
|
|
103
|
+
#
|
|
104
|
+
# @example Declaring a named middleware with some labels
|
|
105
|
+
# MyClass.stack(:foo, :lables => [:demo, :production, :staging]).use(MyMiddleware)
|
|
106
|
+
#
|
|
107
|
+
# This middleware will only be run when pancake is set with the :demo, :production or :staging labels
|
|
108
|
+
#
|
|
109
|
+
# @example A full example
|
|
110
|
+
# MyClass.stack(:foo, :labels => [:staging, :development], :after => :session).use(MyMiddleware)
|
|
111
|
+
#
|
|
112
|
+
#
|
|
113
|
+
# @see Pancake::Middleware#use
|
|
114
|
+
# @api public
|
|
115
|
+
# @since 0.1.0
|
|
116
|
+
# @author Daniel Neighman
|
|
117
|
+
def stack(name = nil, opts = {})
|
|
118
|
+
if self::StackMiddleware._mwares[name] && mw = self::StackMiddleware._mwares[name]
|
|
119
|
+
unless mw.stack == self
|
|
120
|
+
mw = self::StackMiddleware._mwares[name] = self::StackMiddleware._mwares[name].dup
|
|
121
|
+
end
|
|
122
|
+
mw
|
|
123
|
+
else
|
|
124
|
+
self::StackMiddleware.new(name, self, opts)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Adds middleware to the current stack definition
|
|
129
|
+
#
|
|
130
|
+
# @param [Class] middleware The middleware class to use in the stack
|
|
131
|
+
# @param [Hash] opts An options hash that is passed through to the middleware when it is instantiated
|
|
132
|
+
#
|
|
133
|
+
# @yield The block is provided to the middlewares #new method when it is initialized
|
|
134
|
+
#
|
|
135
|
+
# @example Bare use call
|
|
136
|
+
# MyApp.use(MyMiddleware, :some => :option){ # middleware initialization block here }
|
|
137
|
+
#
|
|
138
|
+
# @example Use call after a stack call
|
|
139
|
+
# MyApp.stack(:foo).use(MyMiddleware, :some => :option){ # middleware initialization block here }
|
|
140
|
+
#
|
|
141
|
+
# @see Pancake::Middleware#stack
|
|
142
|
+
# @api public
|
|
143
|
+
# @since 0.1.0
|
|
144
|
+
# @author Daniel Neighman
|
|
145
|
+
def use(middleware, *_args, &block)
|
|
146
|
+
stack(middleware).use(middleware, *_args, &block)
|
|
147
|
+
end # use
|
|
148
|
+
|
|
149
|
+
# StackMiddleware manages the definition of the middleware stack for a given class.
|
|
150
|
+
# It's instances are responsible for the definition of a single piece of middleware, and the class
|
|
151
|
+
# is responsible for specifying the full stack for a given class.
|
|
152
|
+
#
|
|
153
|
+
# When Pancake::Middleware extends a class, an inner class is created in that class called StackMiddleware.
|
|
154
|
+
# That StackMiddleware class inherits from Pancake::Middleware::StackMiddleware.
|
|
155
|
+
#
|
|
156
|
+
# @example The setup when Pancake::Middleware is extended
|
|
157
|
+
# MyClass.extend Pancake::Middleware
|
|
158
|
+
# # sets up
|
|
159
|
+
#
|
|
160
|
+
# class MyClass
|
|
161
|
+
# class StackMiddleware < Pancake::Middleware::StackMiddleware; end
|
|
162
|
+
# end
|
|
163
|
+
#
|
|
164
|
+
# This is then set is an inheritable inner class on the extended class, such that when it is inherited,
|
|
165
|
+
# the StackMiddleware class is inherited to an inner class of the same name on the child.
|
|
166
|
+
class StackMiddleware
|
|
167
|
+
# @api private
|
|
168
|
+
class_inheritable_reader :_central_mwares, :_mwares, :_before, :_after
|
|
169
|
+
@_central_mwares, @_before, @_after, @_mwares = [], {}, {}, {}
|
|
170
|
+
|
|
171
|
+
# @api private
|
|
172
|
+
attr_reader :middleware, :name
|
|
173
|
+
# @api private
|
|
174
|
+
attr_accessor :args, :block, :stack, :options
|
|
175
|
+
|
|
176
|
+
class << self
|
|
177
|
+
def use(mware, *_args, &block)
|
|
178
|
+
new(mware).use(mware, *_args, &block)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Resets this stack middlware. Useful for specs
|
|
182
|
+
def reset!
|
|
183
|
+
_central_mwares.clear
|
|
184
|
+
_mwares.clear
|
|
185
|
+
_before.clear
|
|
186
|
+
_after.clear
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Get the middleware list for this StackMiddleware for the given labels
|
|
190
|
+
#
|
|
191
|
+
# @param [Symbol] labels The label or list of labels to construct a stack from.
|
|
192
|
+
#
|
|
193
|
+
# @example Specified labels
|
|
194
|
+
# MyClass::StackMiddleware.middlewares(:production, :demo)
|
|
195
|
+
#
|
|
196
|
+
# @example No Labels Specified
|
|
197
|
+
# MyClass::StackMiddleware.middlewares
|
|
198
|
+
#
|
|
199
|
+
# This will include all defined middlewares in the given stack
|
|
200
|
+
#
|
|
201
|
+
# @return [Array<StackMiddleware>]
|
|
202
|
+
# An array of the middleware definitions to use in the order that they should be applied
|
|
203
|
+
# Takes into account all :before, :after settings and only constructs the stack where
|
|
204
|
+
# the labels are applied
|
|
205
|
+
#
|
|
206
|
+
# @see Pancake.stack_labels for a description on stack labels
|
|
207
|
+
# @api public
|
|
208
|
+
# @since 0.1.0
|
|
209
|
+
# @author Daniel Neighman
|
|
210
|
+
def middlewares(*labels)
|
|
211
|
+
_central_mwares.map do |name|
|
|
212
|
+
map_middleware(name, *labels)
|
|
213
|
+
end.flatten
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Map the middleware for a given <name>ed middleware. Applies the before and after groups of middlewares
|
|
217
|
+
#
|
|
218
|
+
# @param [Object] name The name of the middleware to map the before and after groups to
|
|
219
|
+
# @param [Symbol] labels A label or list of labels to use to construct the middleware stack
|
|
220
|
+
#
|
|
221
|
+
# @example
|
|
222
|
+
# MyClass::StackMiddleware.map_middleware(:foo, :production, :demo)
|
|
223
|
+
#
|
|
224
|
+
# Constructs the middleware list based on the middleware named :foo, including all :before, and :after groups
|
|
225
|
+
#
|
|
226
|
+
# @return [Array<StackMiddleware>]
|
|
227
|
+
# Provides an array of StackMiddleware instances in the array [<before :foo>, <:foo>, <after :foo>]
|
|
228
|
+
#
|
|
229
|
+
# @api private
|
|
230
|
+
# @since 0.1.0
|
|
231
|
+
# @author Daniel Neighman
|
|
232
|
+
def map_middleware(name, *labels)
|
|
233
|
+
result = []
|
|
234
|
+
_before[name] ||= []
|
|
235
|
+
_after[name] ||= []
|
|
236
|
+
if _mwares[name] && _mwares[name].use_for_labels?(*labels)
|
|
237
|
+
result << _before[name].map{|n| map_middleware(n)}
|
|
238
|
+
result << _mwares[name]
|
|
239
|
+
result << _after[name].map{|n| map_middleware(n)}
|
|
240
|
+
result.flatten
|
|
241
|
+
end
|
|
242
|
+
result
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Provides access to a named middleware
|
|
246
|
+
#
|
|
247
|
+
# @param [Object] name The name of the defined middleware
|
|
248
|
+
#
|
|
249
|
+
# @return [StackMiddleware] The middleware definition associated with <name>
|
|
250
|
+
#
|
|
251
|
+
# @api public
|
|
252
|
+
# @since 0.1.0
|
|
253
|
+
# @author Daniel Neighman
|
|
254
|
+
def [](name)
|
|
255
|
+
_mwares[name]
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Provides access to a named middleware
|
|
260
|
+
#
|
|
261
|
+
# @see Pancake::Middleware::StackMiddleware.[] for an explaination
|
|
262
|
+
# @since 0.1.0
|
|
263
|
+
# @author Daniel Neighman
|
|
264
|
+
def [](name)
|
|
265
|
+
self.class._mwares[name]
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# @param [Object] name a name for this middleware definition. Usually a symbol, but could be the class.
|
|
269
|
+
# @param [Object] stack the stack owner of this middleware.
|
|
270
|
+
# @param [Hash] options an options hash. Provide labels for this middleware.
|
|
271
|
+
# @option options [Array] :labels ([:any])
|
|
272
|
+
# The labels that are associated with this middleware
|
|
273
|
+
# @option options [Object] :before A middleware name to add this middleware before
|
|
274
|
+
# @option options [Object] :after A middleware name to add this middleware after
|
|
275
|
+
#
|
|
276
|
+
# @see Pancake::Middleware.stack_labels
|
|
277
|
+
# @api private
|
|
278
|
+
# @author Daniel Neighman
|
|
279
|
+
def initialize(name, stack, options = {})
|
|
280
|
+
@name, @stack, @options = name, stack, options
|
|
281
|
+
@options[:labels] ||= [:any]
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# Delete this middleware from the current stack
|
|
285
|
+
#
|
|
286
|
+
# @api public
|
|
287
|
+
# @since 0.1.0
|
|
288
|
+
# @author Daniel Neighman
|
|
289
|
+
def delete!
|
|
290
|
+
self.class._mwares.delete(name)
|
|
291
|
+
self.class._before.delete(name)
|
|
292
|
+
self.class._after.delete(name)
|
|
293
|
+
self.class._central_mwares.delete(name)
|
|
294
|
+
self
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
# Specify the actual middleware definition to use
|
|
298
|
+
#
|
|
299
|
+
# @param [Class] mware A Middleware class to use. This should be a class of Middleware which conforms to the Rack spec
|
|
300
|
+
# @param [Hash] config A configuration hash to give to the middleware class on initialization
|
|
301
|
+
# @yield The block is passed to the middleware on initialization
|
|
302
|
+
#
|
|
303
|
+
# @see Pancake::Middleware.use
|
|
304
|
+
# @api public
|
|
305
|
+
# @since 0.1.0
|
|
306
|
+
# @author Daniel Neighman
|
|
307
|
+
def use(mware, *_args, &block)
|
|
308
|
+
@middleware, @args, @block = mware, _args, block
|
|
309
|
+
@name = @middleware if name.nil?
|
|
310
|
+
if options[:before]
|
|
311
|
+
raise "#{options[:before].inspect} middleware is not defined for this stack" unless self.class._mwares.keys.include?(options[:before])
|
|
312
|
+
self.class._before[options[:before]] ||= []
|
|
313
|
+
self.class._before[options[:before]] << name
|
|
314
|
+
elsif options[:after]
|
|
315
|
+
raise "#{options[:after].inspect} middleware is not defined for this stack" unless self.class._mwares.keys.include?(options[:after])
|
|
316
|
+
self.class._after[options[:after]] ||= []
|
|
317
|
+
self.class._after[options[:after]] << name
|
|
318
|
+
else
|
|
319
|
+
self.class._central_mwares << name unless self.class._central_mwares.include?(name)
|
|
320
|
+
end
|
|
321
|
+
self.class._mwares[name] = self
|
|
322
|
+
self
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Checks if this middleware definition should be included from the labels given
|
|
326
|
+
# @param [Symbol] labels The label or list of labels to check if this middleware should be included
|
|
327
|
+
#
|
|
328
|
+
# @return [Boolean] true if this middlware should be included
|
|
329
|
+
#
|
|
330
|
+
# @api private
|
|
331
|
+
# @since 0.1.0
|
|
332
|
+
# @author Daniel Neighman
|
|
333
|
+
def use_for_labels?(*labels)
|
|
334
|
+
return true if labels.empty? || options[:labels].nil? || options[:labels].include?(:any)
|
|
335
|
+
!(options[:labels] & labels).empty?
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# @api private
|
|
339
|
+
def dup
|
|
340
|
+
result = super
|
|
341
|
+
result.args = result.args.map{|element| element.dup}
|
|
342
|
+
result.options = result.options.dup
|
|
343
|
+
result
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end # Middleware
|
|
347
|
+
end # Pancake
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'logger'
|
|
2
|
+
module Pancake
|
|
3
|
+
module Middlewares
|
|
4
|
+
class Logger
|
|
5
|
+
attr_reader :app
|
|
6
|
+
def initialize(app)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
env[Pancake::Constants::ENV_LOGGER_KEY] ||= Pancake.logger
|
|
12
|
+
@app.call(env)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|