|
983358b3
»
|
Blake Mizerany |
2008-04-15 |
Freezing Rack into package ... |
1 |
Dir[File.dirname(__FILE__) + "/../vendor/*"].each do |l| |
| |
2 |
$:.unshift "#{File.expand_path(l)}/lib" |
| |
3 |
end |
| |
4 |
|
| |
5 |
require 'rack' |
| |
6 |
|
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
7 |
require 'rubygems' |
|
9a5d69a8
»
|
rtomayko |
2008-03-26 |
If-Modified-Since support f... |
8 |
require 'time' |
|
983358b3
»
|
Blake Mizerany |
2008-04-15 |
Freezing Rack into package ... |
9 |
require 'ostruct' |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
10 |
require "uri" |
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
11 |
|
| |
12 |
if ENV['SWIFT'] |
| |
13 |
require 'swiftcore/swiftiplied_mongrel' |
| |
14 |
puts "Using Swiftiplied Mongrel" |
| |
15 |
elsif ENV['EVENT'] |
| |
16 |
require 'swiftcore/evented_mongrel' |
| |
17 |
puts "Using Evented Mongrel" |
| |
18 |
end |
| |
19 |
|
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
20 |
class Class |
|
15d360e8
»
|
Markus Prinz |
2008-04-07 |
Fix spelling of dslify_writer |
21 |
def dslify_writer(*syms) |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
22 |
syms.each do |sym| |
| |
23 |
class_eval <<-end_eval |
| |
24 |
def #{sym}(v=nil) |
| |
25 |
self.send "#{sym}=", v if v |
| |
26 |
v |
| |
27 |
end |
| |
28 |
end_eval |
| |
29 |
end |
| |
30 |
end |
| |
31 |
end |
| |
32 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
33 |
module Rack #:nodoc: |
| |
34 |
|
| |
35 |
class Request #:nodoc: |
|
b18102be
»
|
rtomayko |
2008-03-12 |
Fix a few minor issues with... |
36 |
|
| |
37 |
# Set of request method names allowed via the _method parameter hack. By default, |
| |
38 |
# all request methods defined in RFC2616 are included, with the exception of |
| |
39 |
# TRACE and CONNECT. |
| |
40 |
POST_TUNNEL_METHODS_ALLOWED = %w( PUT DELETE OPTIONS HEAD ) |
| |
41 |
|
| |
42 |
# Return the HTTP request method with support for method tunneling using the POST |
| |
43 |
# _method parameter hack. If the real request method is POST and a _method param is |
| |
44 |
# given and the value is one defined in +POST_TUNNEL_METHODS_ALLOWED+, return the value |
| |
45 |
# of the _method param instead. |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
46 |
def request_method |
|
b18102be
»
|
rtomayko |
2008-03-12 |
Fix a few minor issues with... |
47 |
if post_tunnel_method_hack? |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
48 |
params['_method'].upcase |
| |
49 |
else |
| |
50 |
@env['REQUEST_METHOD'] |
| |
51 |
end |
| |
52 |
end |
|
b18102be
»
|
rtomayko |
2008-03-12 |
Fix a few minor issues with... |
53 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
54 |
def user_agent |
|
9c875ffd
»
|
Blake Mizerany |
2008-04-20 |
Session testing made easy |
55 |
@env['HTTP_USER_AGENT'] |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
56 |
end |
|
b18102be
»
|
rtomayko |
2008-03-12 |
Fix a few minor issues with... |
57 |
|
|
9c413351
»
|
adamwiggins |
2008-06-08 |
:accept option to filter on... |
58 |
def accept |
| |
59 |
@env['HTTP_ACCEPT'].split(',').map { |a| a.strip } |
| |
60 |
end |
| |
61 |
|
|
b18102be
»
|
rtomayko |
2008-03-12 |
Fix a few minor issues with... |
62 |
private |
| |
63 |
|
| |
64 |
# Return truthfully if and only if the following conditions are met: 1.) the |
| |
65 |
# *actual* request method is POST, 2.) the request content-type is one of |
| |
66 |
# 'application/x-www-form-urlencoded' or 'multipart/form-data', 3.) there is a |
| |
67 |
# "_method" parameter in the POST body (not in the query string), and 4.) the |
| |
68 |
# method parameter is one of the verbs listed in the POST_TUNNEL_METHODS_ALLOWED |
| |
69 |
# list. |
| |
70 |
def post_tunnel_method_hack? |
| |
71 |
@env['REQUEST_METHOD'] == 'POST' && |
| |
72 |
POST_TUNNEL_METHODS_ALLOWED.include?(self.POST.fetch('_method', '').upcase) |
| |
73 |
end |
| |
74 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
75 |
end |
| |
76 |
|
|
327c6ece
»
|
rtomayko |
2008-03-08 |
Fix that built-in error mes... |
77 |
module Utils |
| |
78 |
extend self |
| |
79 |
end |
| |
80 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
81 |
end |
| |
82 |
|
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
83 |
module Sinatra |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
84 |
extend self |
|
095d95e3
»
|
Blake Mizerany |
2007-11-27 |
refactored |
85 |
|
|
1776a80d
»
|
Blake Mizerany |
2008-03-24 |
Added Version and Docs |
86 |
module Version |
| |
87 |
MAJOR = '0' |
| |
88 |
MINOR = '2' |
|
08b1452a
»
|
bmizerany |
2008-05-07 |
getting ready for 0.2.3 |
89 |
REVISION = '3' |
|
1776a80d
»
|
Blake Mizerany |
2008-03-24 |
Added Version and Docs |
90 |
def self.combined |
| |
91 |
[MAJOR, MINOR, REVISION].join('.') |
| |
92 |
end |
| |
93 |
end |
| |
94 |
|
|
1f07ba27
»
|
Blake Mizerany |
2008-02-24 |
No more Error codes. Map t... |
95 |
class NotFound < RuntimeError; end |
| |
96 |
class ServerError < RuntimeError; end |
| |
97 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
98 |
Result = Struct.new(:block, :params, :status) unless defined?(Result) |
|
e0c7f978
»
|
Blake Mizerany |
2008-03-27 |
easy access to options |
99 |
|
| |
100 |
def options |
| |
101 |
application.options |
| |
102 |
end |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
103 |
|
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
104 |
def application |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
105 |
@app ||= Application.new |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
106 |
end |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
107 |
|
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
108 |
def application=(app) |
| |
109 |
@app = app |
| |
110 |
end |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
111 |
|
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
112 |
def port |
| |
113 |
application.options.port |
| |
114 |
end |
| |
115 |
|
| |
116 |
def env |
| |
117 |
application.options.env |
| |
118 |
end |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
119 |
|
| |
120 |
# Deprecated: use application instead of build_application. |
| |
121 |
alias :build_application :application |
| |
122 |
|
|
f747bfe4
»
|
Blake Mizerany |
2008-04-14 |
pick a server, any server! |
123 |
def server |
|
7526dacf
»
|
cypher |
2008-05-20 |
Simplify the Sinatra.server... |
124 |
options.server ||= defined?(Rack::Handler::Thin) ? "thin" : "mongrel" |
| |
125 |
# Convert the server into the actual handler name |
| |
126 |
handler = options.server.capitalize.sub(/cgi$/, 'CGI') |
| |
127 |
@server ||= eval("Rack::Handler::#{handler}") |
|
f747bfe4
»
|
Blake Mizerany |
2008-04-14 |
pick a server, any server! |
128 |
end |
| |
129 |
|
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
130 |
def run |
| |
131 |
begin |
|
f747bfe4
»
|
Blake Mizerany |
2008-04-14 |
pick a server, any server! |
132 |
puts "== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}" |
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
133 |
require 'pp' |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
134 |
server.run(application, :Port => port) do |server| |
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
135 |
trap(:INT) do |
| |
136 |
server.stop |
| |
137 |
puts "\n== Sinatra has ended his set (crowd applauds)" |
| |
138 |
end |
| |
139 |
end |
| |
140 |
rescue Errno::EADDRINUSE => e |
| |
141 |
puts "== Someone is already performing on port #{port}!" |
| |
142 |
end |
| |
143 |
end |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
144 |
|
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
145 |
class Event |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
146 |
|
|
9ee50b30
»
|
Blake Mizerany |
2007-11-29 |
* Default error messages |
147 |
URI_CHAR = '[^/?:,&#\.]'.freeze unless defined?(URI_CHAR) |
|
9c85e99c
»
|
vic |
2008-04-24 |
Specs, documentation and fi... |
148 |
PARAM = /(:(#{URI_CHAR}+)|\*)/.freeze unless defined?(PARAM) |
|
bf896df2
»
|
Blake Mizerany |
2008-01-11 |
* Splat works |
149 |
SPLAT = /(.*?)/ |
| |
150 |
attr_reader :path, :block, :param_keys, :pattern, :options |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
151 |
|
|
bf896df2
»
|
Blake Mizerany |
2008-01-11 |
* Splat works |
152 |
def initialize(path, options = {}, &b) |
|
53c6609f
»
|
Markus Prinz |
2008-04-11 |
Deal correctly with paths t... |
153 |
@path = URI.encode(path) |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
154 |
@block = b |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
155 |
@param_keys = [] |
|
bf896df2
»
|
Blake Mizerany |
2008-01-11 |
* Splat works |
156 |
@options = options |
|
9c85e99c
»
|
vic |
2008-04-24 |
Specs, documentation and fi... |
157 |
splats = 0 |
| |
158 |
regex = @path.to_s.gsub(PARAM) do |match| |
| |
159 |
if match == "*" |
| |
160 |
@param_keys << "_splat_#{splats}" |
| |
161 |
splats += 1 |
| |
162 |
SPLAT.to_s |
| |
163 |
else |
| |
164 |
@param_keys << $2 |
| |
165 |
"(#{URI_CHAR}+)" |
| |
166 |
end |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
167 |
end |
|
9c85e99c
»
|
vic |
2008-04-24 |
Specs, documentation and fi... |
168 |
|
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
169 |
@pattern = /^#{regex}$/ |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
170 |
end |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
171 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
172 |
def invoke(request) |
|
0b485a96
»
|
Blake Mizerany |
2008-03-24 |
capture agent captures in p... |
173 |
params = {} |
|
d71fe830
»
|
Blake Mizerany |
2008-04-01 |
filter on host |
174 |
if agent = options[:agent] |
| |
175 |
return unless request.user_agent =~ agent |
|
0b485a96
»
|
Blake Mizerany |
2008-03-24 |
capture agent captures in p... |
176 |
params[:agent] = $~[1..-1] |
|
bf896df2
»
|
Blake Mizerany |
2008-01-11 |
* Splat works |
177 |
end |
|
d71fe830
»
|
Blake Mizerany |
2008-04-01 |
filter on host |
178 |
if host = options[:host] |
| |
179 |
return unless host === request.host |
| |
180 |
end |
|
9c413351
»
|
adamwiggins |
2008-06-08 |
:accept option to filter on... |
181 |
if accept = options[:accept] |
| |
182 |
return unless request.accept.include? accept |
| |
183 |
end |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
184 |
return unless pattern =~ request.path_info.squeeze('/') |
|
0b485a96
»
|
Blake Mizerany |
2008-03-24 |
capture agent captures in p... |
185 |
params.merge!(param_keys.zip($~.captures.map(&:from_param)).to_hash) |
|
9c85e99c
»
|
vic |
2008-04-24 |
Specs, documentation and fi... |
186 |
splats = params.select { |k, v| k =~ /^_splat_\d+$/ }.sort.map(&:last) |
| |
187 |
unless splats.empty? |
| |
188 |
params.delete_if { |k, v| k =~ /^_splat_\d+$/ } |
| |
189 |
params["splat"] = splats |
| |
190 |
end |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
191 |
Result.new(block, params, 200) |
|
095d95e3
»
|
Blake Mizerany |
2007-11-27 |
refactored |
192 |
end |
| |
193 |
|
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
194 |
end |
| |
195 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
196 |
class Error |
| |
197 |
|
| |
198 |
attr_reader :code, :block |
| |
199 |
|
| |
200 |
def initialize(code, &b) |
| |
201 |
@code, @block = code, b |
| |
202 |
end |
| |
203 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
204 |
def invoke(request) |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
205 |
Result.new(block, {}, 404) |
| |
206 |
end |
|
53856731
»
|
Blake Mizerany |
2007-11-27 |
in context |
207 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
208 |
end |
| |
209 |
|
|
13d13b21
»
|
Blake Mizerany |
2007-12-02 |
static files |
210 |
class Static |
| |
211 |
|
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
212 |
def invoke(request) |
|
13d13b21
»
|
Blake Mizerany |
2007-12-02 |
static files |
213 |
return unless File.file?( |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
214 |
Sinatra.application.options.public + request.path_info.http_unescape |
|
13d13b21
»
|
Blake Mizerany |
2007-12-02 |
static files |
215 |
) |
| |
216 |
Result.new(block, {}, 200) |
| |
217 |
end |
| |
218 |
|
| |
219 |
def block |
| |
220 |
Proc.new do |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
221 |
send_file Sinatra.application.options.public + request.path_info.http_unescape, |
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
222 |
:disposition => nil |
|
13d13b21
»
|
Blake Mizerany |
2007-12-02 |
static files |
223 |
end |
| |
224 |
end |
| |
225 |
|
| |
226 |
end |
| |
227 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
228 |
# Adapted from actionpack |
| |
229 |
# Methods for sending files and streams to the browser instead of rendering. |
| |
230 |
module Streaming |
| |
231 |
DEFAULT_SEND_FILE_OPTIONS = { |
| |
232 |
:type => 'application/octet-stream'.freeze, |
| |
233 |
:disposition => 'attachment'.freeze, |
| |
234 |
:stream => true, |
| |
235 |
:buffer_size => 4096 |
| |
236 |
}.freeze |
| |
237 |
|
|
1bcd28fa
»
|
Blake Mizerany |
2008-03-31 |
merge in env to test methods |
238 |
class MissingFile < RuntimeError; end |
| |
239 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
240 |
class FileStreamer |
| |
241 |
|
| |
242 |
attr_reader :path, :options |
| |
243 |
|
| |
244 |
def initialize(path, options) |
| |
245 |
@path, @options = path, options |
| |
246 |
end |
| |
247 |
|
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
248 |
def to_result(cx, *args) |
| |
249 |
self |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
250 |
end |
| |
251 |
|
| |
252 |
def each |
| |
253 |
File.open(path, 'rb') do |file| |
| |
254 |
while buf = file.read(options[:buffer_size]) |
| |
255 |
yield buf |
| |
256 |
end |
| |
257 |
end |
| |
258 |
end |
| |
259 |
|
| |
260 |
end |
| |
261 |
|
| |
262 |
protected |
| |
263 |
# Sends the file by streaming it 4096 bytes at a time. This way the |
| |
264 |
# whole file doesn't need to be read into memory at once. This makes |
| |
265 |
# it feasible to send even large files. |
| |
266 |
# |
| |
267 |
# Be careful to sanitize the path parameter if it coming from a web |
| |
268 |
# page. send_file(params[:path]) allows a malicious user to |
| |
269 |
# download any file on your server. |
| |
270 |
# |
| |
271 |
# Options: |
| |
272 |
# * <tt>:filename</tt> - suggests a filename for the browser to use. |
| |
273 |
# Defaults to File.basename(path). |
| |
274 |
# * <tt>:type</tt> - specifies an HTTP content type. |
| |
275 |
# Defaults to 'application/octet-stream'. |
| |
276 |
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. |
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
277 |
# Valid values are 'inline' and 'attachment' (default). When set to nil, the |
| |
278 |
# Content-Disposition and Content-Transfer-Encoding headers are omitted entirely. |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
279 |
# * <tt>:stream</tt> - whether to send the file to the user agent as it is read (true) |
| |
280 |
# or to read the entire file before sending (false). Defaults to true. |
| |
281 |
# * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file. |
| |
282 |
# Defaults to 4096. |
| |
283 |
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. |
|
9a5d69a8
»
|
rtomayko |
2008-03-26 |
If-Modified-Since support f... |
284 |
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value (See Time#httpdate) |
| |
285 |
# indicating the last modified time of the file. If the request includes an |
| |
286 |
# If-Modified-Since header that matches this value exactly, a 304 Not Modified response |
| |
287 |
# is sent instead of the file. Defaults to the file's last modified |
| |
288 |
# time. |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
289 |
# |
| |
290 |
# The default Content-Type and Content-Disposition headers are |
| |
291 |
# set to download arbitrary binary files in as many browsers as |
| |
292 |
# possible. IE versions 4, 5, 5.5, and 6 are all known to have |
| |
293 |
# a variety of quirks (especially when downloading over SSL). |
| |
294 |
# |
| |
295 |
# Simple download: |
| |
296 |
# send_file '/path/to.zip' |
| |
297 |
# |
| |
298 |
# Show a JPEG in the browser: |
| |
299 |
# send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline' |
| |
300 |
# |
| |
301 |
# Show a 404 page in the browser: |
| |
302 |
# send_file '/path/to/404.html, :type => 'text/html; charset=utf-8', :status => 404 |
| |
303 |
# |
| |
304 |
# Read about the other Content-* HTTP headers if you'd like to |
| |
305 |
# provide the user with more information (such as Content-Description). |
| |
306 |
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 |
| |
307 |
# |
| |
308 |
# Also be aware that the document may be cached by proxies and browsers. |
| |
309 |
# The Pragma and Cache-Control headers declare how the file may be cached |
| |
310 |
# by intermediaries. They default to require clients to validate with |
| |
311 |
# the server before releasing cached responses. See |
| |
312 |
# http://www.mnot.net/cache_docs/ for an overview of web caching and |
| |
313 |
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 |
| |
314 |
# for the Cache-Control header spec. |
| |
315 |
def send_file(path, options = {}) #:doc: |
| |
316 |
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path) |
| |
317 |
|
| |
318 |
options[:length] ||= File.size(path) |
| |
319 |
options[:filename] ||= File.basename(path) |
| |
320 |
options[:type] ||= Rack::File::MIME_TYPES[File.extname(options[:filename])[1..-1]] || 'text/plain' |
|
9a5d69a8
»
|
rtomayko |
2008-03-26 |
If-Modified-Since support f... |
321 |
options[:last_modified] ||= File.mtime(path).httpdate |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
322 |
send_file_headers! options |
| |
323 |
|
| |
324 |
if options[:stream] |
| |
325 |
throw :halt, [options[:status] || 200, FileStreamer.new(path, options)] |
| |
326 |
else |
| |
327 |
File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, file.read] } |
| |
328 |
end |
| |
329 |
end |
| |
330 |
|
| |
331 |
# Send binary data to the user as a file download. May set content type, apparent file name, |
| |
332 |
# and specify whether to show data inline or download as an attachment. |
| |
333 |
# |
| |
334 |
# Options: |
| |
335 |
# * <tt>:filename</tt> - Suggests a filename for the browser to use. |
| |
336 |
# * <tt>:type</tt> - specifies an HTTP content type. |
| |
337 |
# Defaults to 'application/octet-stream'. |
| |
338 |
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. |
| |
339 |
# Valid values are 'inline' and 'attachment' (default). |
| |
340 |
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. |
|
9a5d69a8
»
|
rtomayko |
2008-03-26 |
If-Modified-Since support f... |
341 |
# * <tt>:last_modified</tt> - an optional RFC 2616 formatted date value (See Time#httpdate) |
| |
342 |
# indicating the last modified time of the response entity. If the request includes an |
| |
343 |
# If-Modified-Since header that matches this value exactly, a 304 Not Modified response |
| |
344 |
# is sent instead of the data. |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
345 |
# |
| |
346 |
# Generic data download: |
| |
347 |
# send_data buffer |
| |
348 |
# |
| |
349 |
# Download a dynamically-generated tarball: |
| |
350 |
# send_data generate_tgz('dir'), :filename => 'dir.tgz' |
| |
351 |
# |
| |
352 |
# Display an image Active Record in the browser: |
| |
353 |
# send_data image.data, :type => image.content_type, :disposition => 'inline' |
| |
354 |
# |
| |
355 |
# See +send_file+ for more information on HTTP Content-* headers and caching. |
| |
356 |
def send_data(data, options = {}) #:doc: |
| |
357 |
send_file_headers! options.merge(:length => data.size) |
| |
358 |
throw :halt, [options[:status] || 200, data] |
| |
359 |
end |
| |
360 |
|
| |
361 |
private |
| |
362 |
def send_file_headers!(options) |
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
363 |
options = DEFAULT_SEND_FILE_OPTIONS.merge(options) |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
364 |
[:length, :type, :disposition].each do |arg| |
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
365 |
raise ArgumentError, ":#{arg} option required" unless options.key?(arg) |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
366 |
end |
| |
367 |
|
|
9a5d69a8
»
|
rtomayko |
2008-03-26 |
If-Modified-Since support f... |
368 |
# Send a "304 Not Modified" if the last_modified option is provided and matches |
| |
369 |
# the If-Modified-Since request header value. |
| |
370 |
if last_modified = options[:last_modified] |
| |
371 |
header 'Last-Modified' => last_modified |
| |
372 |
throw :halt, [ 304, '' ] if last_modified == request.env['HTTP_IF_MODIFIED_SINCE'] |
| |
373 |
end |
| |
374 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
375 |
headers( |
| |
376 |
'Content-Length' => options[:length].to_s, |
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
377 |
'Content-Type' => options[:type].strip # fixes a problem with extra '\r' with some browsers |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
378 |
) |
| |
379 |
|
|
bacfa20d
»
|
rtomayko |
2008-03-26 |
Make Static omit Content-Di... |
380 |
# Omit Content-Disposition and Content-Transfer-Encoding headers if |
| |
381 |
# the :disposition option set to nil. |
| |
382 |
if !options[:disposition].nil? |
| |
383 |
disposition = options[:disposition].dup || 'attachment' |
| |
384 |
disposition <<= %(; filename="#{options[:filename]}") if options[:filename] |
| |
385 |
headers 'Content-Disposition' => disposition, 'Content-Transfer-Encoding' => 'binary' |
| |
386 |
end |
| |
387 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
388 |
# Fix a problem with IE 6.0 on opening downloaded files: |
| |
389 |
# If Cache-Control: no-cache is set (which Rails does by default), |
| |
390 |
# IE removes the file it just downloaded from its cache immediately |
| |
391 |
# after it displays the "open/save" dialog, which means that if you |
| |
392 |
# hit "open" the file isn't there anymore when the application that |
| |
393 |
# is called for handling the download is run, so let's workaround that |
| |
394 |
header('Cache-Control' => 'private') if headers['Cache-Control'] == 'no-cache' |
| |
395 |
end |
| |
396 |
end |
|
d343d27d
»
|
rtomayko |
2008-04-13 |
document and further spec o... |
397 |
|
| |
398 |
|
| |
399 |
# Helper methods for building various aspects of the HTTP response. |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
400 |
module ResponseHelpers |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
401 |
|
|
d343d27d
»
|
rtomayko |
2008-04-13 |
document and further spec o... |
402 |
# Immediately halt response execution by redirecting to the resource |
| |
403 |
# specified. The +path+ argument may be an absolute URL or a path |
| |
404 |
# relative to the site root. Additional arguments are passed to the |
| |
405 |
# halt. |
| |
406 |
# |
| |
407 |
# With no integer status code, a '302 Temporary Redirect' response is |
| |
408 |
# sent. To send a permanent redirect, pass an explicit status code of |
| |
409 |
# 301: |
| |
410 |
# |
| |
411 |
# redirect '/somewhere/else', 301 |
| |
412 |
# |
| |
413 |
# NOTE: No attempt is made to rewrite the path based on application |
| |
414 |
# context. The 'Location' response header is set verbatim to the value |
| |
415 |
# provided. |
|
d41cccae
»
|
Blake Mizerany |
2008-02-20 |
less code = great code |
416 |
def redirect(path, *args) |
| |
417 |
status(302) |
|
d343d27d
»
|
rtomayko |
2008-04-13 |
document and further spec o... |
418 |
header 'Location' => path |
|
d41cccae
»
|
Blake Mizerany |
2008-02-20 |
less code = great code |
419 |
throw :halt, *args |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
420 |
end |
|
d343d27d
»
|
rtomayko |
2008-04-13 |
document and further spec o... |
421 |
|
| |
422 |
# Access or modify response headers. With no argument, return the |
| |
423 |
# underlying headers Hash. With a Hash argument, add or overwrite |
| |
424 |
# existing response headers with the values provided: |
| |
425 |
# |
|
ccc19b04
»
|
rtomayko |
2008-04-13 |
content_type response helpe... |
426 |
# headers 'Content-Type' => "text/html;charset=utf-8", |
|
d343d27d
»
|
rtomayko |
2008-04-13 |
document and further spec o... |
427 |
# 'Last-Modified' => Time.now.httpdate, |
| |
428 |
# 'X-UA-Compatible' => 'IE=edge' |
| |
429 |
# |
| |
430 |
# This method also available in singular form (#header). |
|
038b6b7d
»
|
Blake Mizerany |
2008-02-17 |
Quick changes |
431 |
def headers(header = nil) |
| |
432 |
@response.headers.merge!(header) if header |
| |
433 |
@response.headers |
| |
434 |
end |
| |
435 |
alias :header :headers |
| |
436 |
|
|
ccc19b04
»
|
rtomayko |
2008-04-13 |
content_type response helpe... |
437 |
# Set the content type of the response body (HTTP 'Content-Type' header). |
| |
438 |
# |
| |
439 |
# The +type+ argument may be an internet media type (e.g., 'text/html', |
| |
440 |
# 'application/xml+atom', 'image/png') or a Symbol key into the |
| |
441 |
# Rack::File::MIME_TYPES table. |
| |
442 |
# |
| |
443 |
# Media type parameters, such as "charset", may also be specified using the |
| |
444 |
# optional hash argument: |
| |
445 |
# |
| |
446 |
# get '/foo.html' do |
| |
447 |
# content_type 'text/html', :charset => 'utf-8' |
| |
448 |
# "<h1>Hello World</h1>" |
| |
449 |
# end |
| |
450 |
# |
| |
451 |
def content_type(type, params={}) |
| |
452 |
type = Rack::File::MIME_TYPES[type.to_s] if type.kind_of?(Symbol) |
| |
453 |
fail "Invalid or undefined media_type: #{type}" if type.nil? |
| |
454 |
if params.any? |
|
540aa5fa
»
|
Blake Mizerany |
2008-04-15 |
Revert "refactored content_... |
455 |
params = params.collect { |kv| "%s=%s" % kv }.join(', ') |
|
ccc19b04
»
|
rtomayko |
2008-04-13 |
content_type response helpe... |
456 |
type = [ type, params ].join(";") |
| |
457 |
end |
| |
458 |
response.header['Content-Type'] = type |
| |
459 |
end |
| |
460 |
|
|
302a03cc
»
|
rtomayko |
2008-03-31 |
last_modified response help... |
461 |
# Set the last modified time of the resource (HTTP 'Last-Modified' header) |
| |
462 |
# and halt if conditional GET matches. The +time+ argument is a Time, |
| |
463 |
# DateTime, or other object that responds to +to_time+. |
| |
464 |
# |
| |
465 |
# When the current request includes an 'If-Modified-Since' header that |
| |
466 |
# matches the time specified, execution is immediately halted with a |
| |
467 |
# '304 Not Modified' response. |
| |
468 |
# |
| |
469 |
# Calling this method before perfoming heavy processing (e.g., lengthy |
| |
470 |
# database queries, template rendering, complex logic) can dramatically |
| |
471 |
# increase overall throughput with caching clients. |
| |
472 |
def last_modified(time) |
| |
473 |
time = time.to_time if time.respond_to?(:to_time) |
| |
474 |
time = time.httpdate if time.respond_to?(:httpdate) |
| |
475 |
response.header['Last-Modified'] = time |
| |
476 |
throw :halt, 304 if time == request.env['HTTP_IF_MODIFIED_SINCE'] |
| |
477 |
time |
| |
478 |
end |
| |
479 |
|
|
ce4cf34e
»
|
rtomayko |
2008-04-13 |
entity_tag response helper ... |
480 |
# Set the response entity tag (HTTP 'ETag' header) and halt if conditional |
| |
481 |
# GET matches. The +value+ argument is an identifier that uniquely |
| |
482 |
# identifies the current version of the resource. The +strength+ argument |
| |
483 |
# indicates whether the etag should be used as a :strong (default) or :weak |
| |
484 |
# cache validator. |
| |
485 |
# |
| |
486 |
# When the current request includes an 'If-None-Match' header with a |
| |
487 |
# matching etag, execution is immediately halted. If the request method is |
| |
488 |
# GET or HEAD, a '304 Not Modified' response is sent. For all other request |
| |
489 |
# methods, a '412 Precondition Failed' response is sent. |
| |
490 |
# |
| |
491 |
# Calling this method before perfoming heavy processing (e.g., lengthy |
| |
492 |
# database queries, template rendering, complex logic) can dramatically |
| |
493 |
# increase overall throughput with caching clients. |
| |
494 |
# |
|
418db1ed
»
|
rtomayko |
2008-05-19 |
minor rdoc formatting fixes |
495 |
# ==== See Also |
| |
496 |
# {RFC2616: ETag}[http://w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19], |
|
ce4cf34e
»
|
rtomayko |
2008-04-13 |
entity_tag response helper ... |
497 |
# ResponseHelpers#last_modified |
| |
498 |
def entity_tag(value, strength=:strong) |
| |
499 |
value = |
| |
500 |
case strength |
| |
501 |
when :strong then '"%s"' % value |
| |
502 |
when :weak then 'W/"%s"' % value |
| |
503 |
else raise TypeError, "strength must be one of :strong or :weak" |
| |
504 |
end |
| |
505 |
response.header['ETag'] = value |
| |
506 |
|
| |
507 |
# Check for If-None-Match request header and halt if match is found. |
| |
508 |
etags = (request.env['HTTP_IF_NONE_MATCH'] || '').split(/\s*,\s*/) |
| |
509 |
if etags.include?(value) || etags.include?('*') |
| |
510 |
# GET/HEAD requests: send Not Modified response |
| |
511 |
throw :halt, 304 if request.get? || request.head? |
| |
512 |
# Other requests: send Precondition Failed response |
| |
513 |
throw :halt, 412 |
| |
514 |
end |
| |
515 |
end |
| |
516 |
|
| |
517 |
alias :etag :entity_tag |
| |
518 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
519 |
end |
|
ccc19b04
»
|
rtomayko |
2008-04-13 |
content_type response helpe... |
520 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
521 |
module RenderingHelpers |
|
becd6d8a
»
|
Blake Mizerany |
2008-02-20 |
ERB in place |
522 |
|
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
523 |
def render(renderer, template, options={}) |
| |
524 |
m = method("render_#{renderer}") |
|
3d92391a
»
|
Blake Mizerany |
2008-03-22 |
pass locals to haml |
525 |
result = m.call(resolve_template(renderer, template, options), options) |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
526 |
if layout = determine_layout(renderer, template, options) |
|
3d92391a
»
|
Blake Mizerany |
2008-03-22 |
pass locals to haml |
527 |
result = m.call(resolve_template(renderer, layout, options), options) { result } |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
528 |
end |
| |
529 |
result |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
530 |
end |
| |
531 |
|
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
532 |
def determine_layout(renderer, template, options) |
|
898b36ea
»
|
Blake Mizerany |
2008-03-15 |
allow user to prevent layou... |
533 |
return if options[:layout] == false |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
534 |
layout_from_options = options[:layout] || :layout |
|
5e857124
»
|
Blake Mizerany |
2008-03-28 |
tests for use_in_file_templ... |
535 |
resolve_template(renderer, layout_from_options, options, false) |
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
536 |
end |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
537 |
|
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
538 |
private |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
539 |
|
|
ccbb0703
»
|
Blake Mizerany |
2008-02-28 |
FIX: Render without layout |
540 |
def resolve_template(renderer, template, options, scream = true) |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
541 |
case template |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
542 |
when String |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
543 |
template |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
544 |
when Proc |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
545 |
template.call |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
546 |
when Symbol |
|
6bda16b9
»
|
Blake Mizerany |
2008-03-26 |
added `template` to DSL |
547 |
if proc = templates[template] |
|
d874133b
»
|
Blake Mizerany |
2008-03-26 |
inline templates! |
548 |
resolve_template(renderer, proc, options, scream) |
|
6bda16b9
»
|
Blake Mizerany |
2008-03-26 |
added `template` to DSL |
549 |
else |
|
d874133b
»
|
Blake Mizerany |
2008-03-26 |
inline templates! |
550 |
read_template_file(renderer, template, options, scream) |
|
ccbb0703
»
|
Blake Mizerany |
2008-02-28 |
FIX: Render without layout |
551 |
end |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
552 |
else |
| |
553 |
nil |
|
2f6269f6
»
|
Blake Mizerany |
2007-11-28 |
named partials |
554 |
end |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
555 |
end |
|
2f6269f6
»
|
Blake Mizerany |
2007-11-28 |
named partials |
556 |
|
|
d874133b
»
|
Blake Mizerany |
2008-03-26 |
inline templates! |
557 |
def read_template_file(renderer, template, options, scream = true) |
| |
558 |
path = File.join( |
| |
559 |
options[:views_directory] || Sinatra.application.options.views, |
| |
560 |
"#{template}.#{renderer}" |
| |
561 |
) |
| |
562 |
unless File.exists?(path) |
| |
563 |
raise Errno::ENOENT.new(path) if scream |
| |
564 |
nil |
| |
565 |
else |
| |
566 |
File.read(path) |
| |
567 |
end |
| |
568 |
end |
| |
569 |
|
|
6bda16b9
»
|
Blake Mizerany |
2008-03-26 |
added `template` to DSL |
570 |
def templates |
| |
571 |
Sinatra.application.templates |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
572 |
end |
| |
573 |
|
| |
574 |
end |
| |
575 |
|
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
576 |
module Erb |
| |
577 |
|
| |
578 |
def erb(content, options={}) |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
579 |
require 'erb' |
| |
580 |
render(:erb, content, options) |
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
581 |
end |
| |
582 |
|
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
583 |
private |
| |
584 |
|
|
3d92391a
»
|
Blake Mizerany |
2008-03-22 |
pass locals to haml |
585 |
def render_erb(content, options = {}) |
|
c2827e33
»
|
cschneid |
2008-05-27 |
Add :locals option for erb.... |
586 |
locals_opt = options.delete(:locals) || {} |
| |
587 |
|
| |
588 |
locals_code = "" |
| |
589 |
locals_hash = {} |
| |
590 |
locals_opt.each do |key, value| |
| |
591 |
locals_code << "#{key} = locals_hash[:#{key}]\n" |
| |
592 |
locals_hash[:"#{key}"] = value |
| |
593 |
end |
| |
594 |
|
| |
595 |
body = ::ERB.new(content).src |
| |
596 |
eval("#{locals_code}#{body}", binding) |
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
597 |
end |
|
c2827e33
»
|
cschneid |
2008-05-27 |
Add :locals option for erb.... |
598 |
|
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
599 |
end |
| |
600 |
|
| |
601 |
module Haml |
| |
602 |
|
| |
603 |
def haml(content, options={}) |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
604 |
require 'haml' |
| |
605 |
render(:haml, content, options) |
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
606 |
end |
| |
607 |
|
| |
608 |
private |
| |
609 |
|
|
3d92391a
»
|
Blake Mizerany |
2008-03-22 |
pass locals to haml |
610 |
def render_haml(content, options = {}, &b) |
|
f80203ad
»
|
Blake Mizerany |
2008-04-19 |
Let's keep default_options ... |
611 |
haml_options = (options[:options] || {}).merge(Sinatra.options.haml || {}) |
|
23999054
»
|
sr |
2008-04-19 |
Add the possibility to conf... |
612 |
::Haml::Engine.new(content, haml_options).render(options[:scope] || self, options[:locals] || {}, &b) |
|
7d5bc1f0
»
|
Blake Mizerany |
2008-02-27 |
Haml & Erb redo |
613 |
end |
| |
614 |
|
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
615 |
end |
|
caf48570
»
|
rtomayko |
2008-03-08 |
Builder Rendering Helper (.... |
616 |
|
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
617 |
# Generate valid CSS using Sass (part of Haml) |
| |
618 |
# |
|
95ca3f0c
»
|
nmeans |
2008-04-08 |
Modified sass method to all... |
619 |
# Sass templates can be in external files with <tt>.sass</tt> extension or can use Sinatra's |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
620 |
# in_file_templates. In either case, the file can be rendered by passing the name of |
| |
621 |
# the template to the +sass+ method as a symbol. |
| |
622 |
# |
|
95ca3f0c
»
|
nmeans |
2008-04-08 |
Modified sass method to all... |
623 |
# Unlike Haml, Sass does not support a layout file, so the +sass+ method will ignore both |
| |
624 |
# the default <tt>layout.sass</tt> file and any parameters passed in as <tt>:layout</tt> in |
| |
625 |
# the options hash. |
| |
626 |
# |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
627 |
# === Sass Template Files |
| |
628 |
# |
|
95ca3f0c
»
|
nmeans |
2008-04-08 |
Modified sass method to all... |
629 |
# Sass templates can be stored in separate files with a <tt>.sass</tt> |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
630 |
# extension under the view path. |
| |
631 |
# |
| |
632 |
# Example: |
| |
633 |
# get '/stylesheet.css' do |
| |
634 |
# header 'Content-Type' => 'text/css; charset=utf-8' |
| |
635 |
# sass :stylesheet |
| |
636 |
# end |
| |
637 |
# |
| |
638 |
# The "views/stylesheet.sass" file might contain the following: |
| |
639 |
# |
| |
640 |
# body |
| |
641 |
# #admin |
| |
642 |
# :background-color #CCC |
| |
643 |
# #main |
| |
644 |
# :background-color #000 |
| |
645 |
# #form |
| |
646 |
# :border-color #AAA |
| |
647 |
# :border-width 10px |
| |
648 |
# |
| |
649 |
# And yields the following output: |
| |
650 |
# |
| |
651 |
# body #admin { |
| |
652 |
# background-color: #CCC; } |
| |
653 |
# body #main { |
| |
654 |
# background-color: #000; } |
| |
655 |
# |
| |
656 |
# #form { |
| |
657 |
# border-color: #AAA; |
| |
658 |
# border-width: 10px; } |
| |
659 |
# |
| |
660 |
# |
| |
661 |
# NOTE: Haml must be installed or a LoadError will be raised the first time an |
| |
662 |
# attempt is made to render a Sass template. |
| |
663 |
# |
| |
664 |
# See http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html for comprehensive documentation on Sass. |
| |
665 |
|
| |
666 |
|
| |
667 |
module Sass |
| |
668 |
|
|
95ca3f0c
»
|
nmeans |
2008-04-08 |
Modified sass method to all... |
669 |
def sass(content, options = {}) |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
670 |
require 'sass' |
|
95ca3f0c
»
|
nmeans |
2008-04-08 |
Modified sass method to all... |
671 |
|
| |
672 |
# Sass doesn't support a layout, so we override any possible layout here |
| |
673 |
options[:layout] = false |
| |
674 |
|
| |
675 |
render(:sass, content, options) |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
676 |
end |
| |
677 |
|
| |
678 |
private |
| |
679 |
|
| |
680 |
def render_sass(content, options = {}) |
| |
681 |
::Sass::Engine.new(content).render |
| |
682 |
end |
| |
683 |
end |
| |
684 |
|
|
caf48570
»
|
rtomayko |
2008-03-08 |
Builder Rendering Helper (.... |
685 |
# Generating conservative XML content using Builder templates. |
| |
686 |
# |
| |
687 |
# Builder templates can be inline by passing a block to the builder method, or in |
| |
688 |
# external files with +.builder+ extension by passing the name of the template |
| |
689 |
# to the +builder+ method as a Symbol. |
| |
690 |
# |
| |
691 |
# === Inline Rendering |
| |
692 |
# |
| |
693 |
# If the builder method is given a block, the block is called directly with an |
| |
694 |
# +XmlMarkup+ instance and the result is returned as String: |
| |
695 |
# get '/who.xml' do |
| |
696 |
# builder do |xml| |
| |
697 |
# xml.instruct! |
| |
698 |
# xml.person do |
| |
699 |
# xml.name "Francis Albert Sinatra", |
| |
700 |
# :aka => "Frank Sinatra" |
| |
701 |
# xml.email 'frank@capitolrecords.com' |
| |
702 |
# end |
| |
703 |
# end |
| |
704 |
# end |
| |
705 |
# |
| |
706 |
# Yields the following XML: |
| |
707 |
# <?xml version='1.0' encoding='UTF-8'?> |
| |
708 |
# <person> |
| |
709 |
# <name aka='Frank Sinatra'>Francis Albert Sinatra</name> |
| |
710 |
# <email>Frank Sinatra</email> |
| |
711 |
# </person> |
| |
712 |
# |
| |
713 |
# === Builder Template Files |
| |
714 |
# |
| |
715 |
# Builder templates can be stored in separate files with a +.builder+ |
| |
716 |
# extension under the view path. An +XmlMarkup+ object named +xml+ is automatically |
| |
717 |
# made available to template. |
| |
718 |
# |
| |
719 |
# Example: |
| |
720 |
# get '/bio.xml' do |
| |
721 |
# builder :bio |
| |
722 |
# end |
| |
723 |
# |
| |
724 |
# The "views/bio.builder" file might contain the following: |
| |
725 |
# xml.instruct! :xml, :version => '1.1' |
| |
726 |
# xml.person do |
| |
727 |
# xml.name "Francis Albert Sinatra" |
| |
728 |
# xml.aka "Frank Sinatra" |
| |
729 |
# xml.aka "Ol' Blue Eyes" |
| |
730 |
# xml.aka "The Chairman of the Board" |
| |
731 |
# xml.born 'date' => '1915-12-12' do |
| |
732 |
# xml.text! "Hoboken, New Jersey, U.S.A." |
| |
733 |
# end |
| |
734 |
# xml.died 'age' => 82 |
| |
735 |
# end |
| |
736 |
# |
| |
737 |
# And yields the following output: |
| |
738 |
# <?xml version='1.1' encoding='UTF-8'?> |
| |
739 |
# <person> |
| |
740 |
# <name>Francis Albert Sinatra</name> |
| |
741 |
# <aka>Frank Sinatra</aka> |
| |
742 |
# <aka>Ol' Blue Eyes</aka> |
| |
743 |
# <aka>The Chairman of the Board</aka> |
| |
744 |
# <born date='1915-12-12'>Hoboken, New Jersey, U.S.A.</born> |
| |
745 |
# <died age='82' /> |
| |
746 |
# </person> |
| |
747 |
# |
| |
748 |
# NOTE: Builder must be installed or a LoadError will be raised the first time an |
| |
749 |
# attempt is made to render a builder template. |
| |
750 |
# |
| |
751 |
# See http://builder.rubyforge.org/ for comprehensive documentation on Builder. |
| |
752 |
module Builder |
| |
753 |
|
| |
754 |
def builder(content=nil, options={}, &block) |
| |
755 |
options, content = content, nil if content.is_a?(Hash) |
| |
756 |
content = Proc.new { block } if content.nil? |
| |
757 |
render(:builder, content, options) |
| |
758 |
end |
| |
759 |
|
| |
760 |
private |
| |
761 |
|
|
3d92391a
»
|
Blake Mizerany |
2008-03-22 |
pass locals to haml |
762 |
def render_builder(content, options = {}, &b) |
|
caf48570
»
|
rtomayko |
2008-03-08 |
Builder Rendering Helper (.... |
763 |
require 'builder' |
| |
764 |
xml = ::Builder::XmlMarkup.new(:indent => 2) |
| |
765 |
case content |
| |
766 |
when String |
| |
767 |
eval(content, binding, '<BUILDER>', 1) |
| |
768 |
when Proc |
| |
769 |
content.call(xml) |
| |
770 |
end |
| |
771 |
xml.target! |
| |
772 |
end |
| |
773 |
|
| |
774 |
end |
| |
775 |
|
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
776 |
class EventContext |
| |
777 |
|
| |
778 |
include ResponseHelpers |
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
779 |
include Streaming |
|
2f6269f6
»
|
Blake Mizerany |
2007-11-28 |
named partials |
780 |
include RenderingHelpers |
|
520ac2e9
»
|
Blake Mizerany |
2008-02-24 |
Haml |
781 |
include Erb |
| |
782 |
include Haml |
|
caf48570
»
|
rtomayko |
2008-03-08 |
Builder Rendering Helper (.... |
783 |
include Builder |
|
2baa78d9
»
|
nmeans |
2008-04-08 |
Added Sass module and 'sass... |
784 |
include Sass |
|
2f6269f6
»
|
Blake Mizerany |
2007-11-28 |
named partials |
785 |
|
|
53856731
»
|
Blake Mizerany |
2007-11-27 |
in context |
786 |
attr_accessor :request, :response |
| |
787 |
|
|
15d360e8
»
|
Markus Prinz |
2008-04-07 |
Fix spelling of dslify_writer |
788 |
dslify_writer :status, :body |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
789 |
|
|
53856731
»
|
Blake Mizerany |
2007-11-27 |
in context |
790 |
def initialize(request, response, route_params) |
| |
791 |
@request = request |
| |
792 |
@response = response |
| |
793 |
@route_params = route_params |
| |
794 |
@response.body = nil |
| |
795 |
end |
| |
796 |
|
| |
797 |
def params |
|
98572b4d
»
|
Blake Mizerany |
2008-04-08 |
Symbol params back in thank... |
798 |
@params ||= begin |
| |
799 |
h = Hash.new {|h,k| h[k.to_s] if Symbol === k} |
| |
800 |
h.merge(@route_params.merge(@request.params)) |
| |
801 |
end |
|
53856731
»
|
Blake Mizerany |
2007-11-27 |
in context |
802 |
end |
|
307f93c6
»
|
Blake Mizerany |
2008-04-09 |
RESTful testing |
803 |
|
| |
804 |
def data |
| |
805 |
@data ||= params.keys.first |
| |
806 |
end |
|
98572b4d
»
|
Blake Mizerany |
2008-04-08 |
Symbol params back in thank... |
807 |
|
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
808 |
def stop(*args) |
| |
809 |
throw :halt, args |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
810 |
end |
| |
811 |
|
|
de6f9818
»
|
Blake Mizerany |
2007-11-28 |
Using :halt to set body |
812 |
def complete(returned) |
|
9040375d
»
|
Blake Mizerany |
2007-11-28 |
render defaults to body or ... |
813 |
@response.body || returned |
|
53856731
»
|
Blake Mizerany |
2007-11-27 |
in context |
814 |
end |
| |
815 |
|
|
4ce62316
»
|
Markus Prinz |
2008-04-07 |
Add session support, which ... |
816 |
def session |
|
9c875ffd
»
|
Blake Mizerany |
2008-04-20 |
Session testing made easy |
817 |
request.env['rack.session'] ||= {} |
|
4ce62316
»
|
Markus Prinz |
2008-04-07 |
Add session support, which ... |
818 |
end |
| |
819 |
|
|
9040375d
»
|
Blake Mizerany |
2007-11-28 |
render defaults to body or ... |
820 |
private |
|
2f6269f6
»
|
Blake Mizerany |
2007-11-28 |
named partials |
821 |
|
|
de6f9818
»
|
Blake Mizerany |
2007-11-28 |
Using :halt to set body |
822 |
def method_missing(name, *args, &b) |
| |
823 |
@response.send(name, *args, &b) |
| |
824 |
end |
| |
825 |
|
|
414c80a3
»
|
Blake Mizerany |
2007-11-27 |
evaluate in context |
826 |
end |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
827 |
|
| |
828 |
|
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
829 |
# The Application class represents the top-level working area of a |
| |
830 |
# Sinatra app. It provides the DSL for defining various aspects of the |
| |
831 |
# application and implements a Rack compatible interface for dispatching |
| |
832 |
# requests. |
| |
833 |
# |
| |
834 |
# Many of the instance methods defined in this class (#get, #post, |
| |
835 |
# #put, #delete, #layout, #before, #error, #not_found, etc.) are |
| |
836 |
# available at top-level scope. When invoked from top-level, the |
| |
837 |
# messages are forwarded to the "default application" (accessible |
| |
838 |
# at Sinatra::application). |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
839 |
class Application |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
840 |
|
| |
841 |
# Hash of event handlers with request method keys and |
| |
842 |
# arrays of potential handlers as values. |
| |
843 |
attr_reader :events |
| |
844 |
|
| |
845 |
# Hash of error handlers with error status codes as keys and |
| |
846 |
# handlers as values. |
| |
847 |
attr_reader :errors |
| |
848 |
|
| |
849 |
# Hash of template name mappings. |
| |
850 |
attr_reader :templates |
| |
851 |
|
| |
852 |
# Hash of filters with event name keys (:before) and arrays of |
| |
853 |
# handlers as values. |
| |
854 |
attr_reader :filters |
| |
855 |
|
| |
856 |
# Array of objects to clear during reload. The objects in this array |
| |
857 |
# must respond to :clear. |
| |
858 |
attr_reader :clearables |
| |
859 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
860 |
# Object including open attribute methods for modifying Application |
| |
861 |
# configuration. |
| |
862 |
attr_reader :options |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
863 |
|
| |
864 |
# List of methods available from top-level scope. When invoked from |
| |
865 |
# top-level the method is forwarded to the default application |
| |
866 |
# (Sinatra::application). |
| |
867 |
FORWARD_METHODS = %w[ |
|
64a2dee4
»
|
rtomayko |
2008-04-16 |
Add enable/disable methods ... |
868 |
get put post delete head template layout before error not_found |
|
1ba1ceb7
»
|
bmizerany |
2008-05-20 |
added 'set' to FORWARD_METHODS |
869 |
configures configure set set_options set_option enable disable use |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
870 |
] |
| |
871 |
|
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
872 |
# Create a new Application with a default configuration taken |
| |
873 |
# from the default_options Hash. |
| |
874 |
# |
| |
875 |
# NOTE: A default Application is automatically created the first |
| |
876 |
# time any of Sinatra's DSL related methods is invoked so there |
| |
877 |
# is typically no need to create an instance explicitly. See |
| |
878 |
# Sinatra::application for more information. |
| |
879 |
def initialize |
| |
880 |
@reloading = false |
| |
881 |
@clearables = [ |
| |
882 |
@events = Hash.new { |hash, key| hash[key] = [] }, |
| |
883 |
@errors = Hash.new, |
| |
884 |
@filters = Hash.new { |hash, key| hash[key] = [] }, |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
885 |
@templates = Hash.new, |
| |
886 |
@middleware = [] |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
887 |
] |
| |
888 |
@options = OpenStruct.new(self.class.default_options) |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
889 |
load_default_configuration! |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
890 |
end |
| |
891 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
892 |
# Hash of default application configuration options. When a new |
| |
893 |
# Application is created, the #options object takes its initial values |
| |
894 |
# from here. |
| |
895 |
# |
| |
896 |
# Changes to the default_options Hash effect only Application objects |
| |
897 |
# created after the changes are made. For this reason, modifications to |
| |
898 |
# the default_options Hash typically occur at the very beginning of a |
| |
899 |
# file, before any DSL related functions are invoked. |
|
06e2a38f
»
|
Blake Mizerany |
2007-11-29 |
options |
900 |
def self.default_options |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
901 |
return @default_options unless @default_options.nil? |
|
5b3440e2
»
|
JackDanger |
2008-04-19 |
Using a more accurate root ... |
902 |
root = File.expand_path(File.dirname($0)) |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
903 |
@default_options = { |
|
06e2a38f
»
|
Blake Mizerany |
2007-11-29 |
options |
904 |
:run => true, |
| |
905 |
:port => 4567, |
|
13d13b21
»
|
Blake Mizerany |
2007-12-02 |
static files |
906 |
:env => :development, |
|
5b3440e2
»
|
JackDanger |
2008-04-19 |
Using a more accurate root ... |
907 |
:root => root, |
| |
908 |
:views => root + '/views', |
| |
909 |
:public => root + '/public', |
|
4ce62316
»
|
Markus Prinz |
2008-04-07 |
Add session support, which ... |
910 |
:sessions => false, |
|
174d9c8a
»
|
cschneid |
2008-05-18 |
Kernel.load $0 breaks when ... |
911 |
:logging => true, |
|
1753aa97
»
|
cschneid |
2008-05-20 |
Merge from bmizerany |
912 |
:app_file => $0, |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
913 |
:raise_errors => false |
|
06e2a38f
»
|
Blake Mizerany |
2007-11-29 |
options |
914 |
} |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
915 |
load_default_options_from_command_line! |
| |
916 |
@default_options |
|
06e2a38f
»
|
Blake Mizerany |
2007-11-29 |
options |
917 |
end |
|
9b06a2d5
»
|
Blake Mizerany |
2008-01-15 |
simple options |
918 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
919 |
# Search ARGV for command line arguments and update the |
| |
920 |
# Sinatra::default_options Hash accordingly. This method is |
| |
921 |
# invoked the first time the default_options Hash is accessed. |
|
ed063848
»
|
Blake Mizerany |
2008-03-28 |
explain'n |
922 |
# NOTE: Ignores --name so unit/spec tests can run individually |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
923 |
def self.load_default_options_from_command_line! #:nodoc: |
|
9b06a2d5
»
|
Blake Mizerany |
2008-01-15 |
simple options |
924 |
require 'optparse' |
| |
925 |
OptionParser.new do |op| |
| |
926 |
op.on('-p port') { |port| default_options[:port] = port } |
| |
927 |
op.on('-e env') { |env| default_options[:env] = env } |
|
f747bfe4
»
|
Blake Mizerany |
2008-04-14 |
pick a server, any server! |
928 |
op.on('-x') { default_options[:mutex] = true } |
| |
929 |
op.on('-s server') { |server| default_options[:server] = server } |
|
44d2b66d
»
|
Blake Mizerany |
2008-02-20 |
Setup for custom renderers |
930 |
end.parse!(ARGV.dup.select { |o| o !~ /--name/ }) |
|
9b06a2d5
»
|
Blake Mizerany |
2008-01-15 |
simple options |
931 |
end |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
932 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
933 |
# Determine whether the application is in the process of being |
| |
934 |
# reloaded. |
| |
935 |
def reloading? |
| |
936 |
@reloading == true |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
937 |
end |
| |
938 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
939 |
# Yield to the block for configuration if the current environment |
| |
940 |
# matches any included in the +envs+ list. Always yield to the block |
| |
941 |
# when no environment is specified. |
| |
942 |
# |
| |
943 |
# NOTE: configuration blocks are not executed during reloads. |
| |
944 |
def configures(*envs, &b) |
| |
945 |
return if reloading? |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
946 |
yield self if envs.empty? || envs.include?(options.env) |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
947 |
end |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
948 |
|
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
949 |
alias :configure :configures |
| |
950 |
|
|
fd0150da
»
|
rtomayko |
2008-04-15 |
Move set_option(s) to Appli... |
951 |
# When both +option+ and +value+ arguments are provided, set the option |
| |
952 |
# specified. With a single Hash argument, set all options specified in |
| |
953 |
# Hash. Options are available via the Application#options object. |
| |
954 |
# |
| |
955 |
# Setting individual options: |
| |
956 |
# set :port, 80 |
| |
957 |
# set :env, :production |
| |
958 |
# set :views, '/path/to/views' |
| |
959 |
# |
| |
960 |
# Setting multiple options: |
| |
961 |
# set :port => 80, |
| |
962 |
# :env => :production, |
| |
963 |
# :views => '/path/to/views' |
| |
964 |
# |
| |
965 |
def set(option, value=self) |
| |
966 |
if value == self && option.kind_of?(Hash) |
| |
967 |
option.each { |key,val| set(key, val) } |
| |
968 |
else |
| |
969 |
options.send("#{option}=", value) |
| |
970 |
end |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
971 |
end |
|
fd0150da
»
|
rtomayko |
2008-04-15 |
Move set_option(s) to Appli... |
972 |
|
| |
973 |
alias :set_option :set |
| |
974 |
alias :set_options :set |
| |
975 |
|
|
64a2dee4
»
|
rtomayko |
2008-04-16 |
Add enable/disable methods ... |
976 |
# Enable the options specified by setting their values to true. For |
| |
977 |
# example, to enable sessions and logging: |
| |
978 |
# enable :sessions, :logging |
| |
979 |
def enable(*opts) |
| |
980 |
opts.each { |key| set(key, true) } |
|
60130707
»
|
Blake Mizerany |
2007-11-28 |
layouts |
981 |
end |
|
64a2dee4
»
|
rtomayko |
2008-04-16 |
Add enable/disable methods ... |
982 |
|
| |
983 |
# Disable the options specified by setting their values to false. For |
| |
984 |
# example, to disable logging and automatic run: |
| |
985 |
# disable :logging, :run |
| |
986 |
def disable(*opts) |
| |
987 |
opts.each { |key| set(key, false) } |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
988 |
end |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
989 |
|
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
990 |
# Define an event handler for the given request method and path |
| |
991 |
# spec. The block is executed when a request matches the method |
| |
992 |
# and spec. |
| |
993 |
# |
| |
994 |
# NOTE: The #get, #post, #put, and #delete helper methods should |
| |
995 |
# be used to define events when possible. |
| |
996 |
def event(method, path, options = {}, &b) |
| |
997 |
events[method].push(Event.new(path, options, &b)).last |
|
b17f5f70
»
|
Blake Mizerany |
2007-11-27 |
simple event lookup |
998 |
end |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
999 |
|
| |
1000 |
# Define an event handler for GET requests. |
| |
1001 |
def get(path, options={}, &b) |
| |
1002 |
event(:get, path, options, &b) |
| |
1003 |
end |
| |
1004 |
|
| |
1005 |
# Define an event handler for POST requests. |
| |
1006 |
def post(path, options={}, &b) |
| |
1007 |
event(:post, path, options, &b) |
| |
1008 |
end |
| |
1009 |
|
| |
1010 |
# Define an event handler for HEAD requests. |
| |
1011 |
def head(path, options={}, &b) |
| |
1012 |
event(:head, path, options, &b) |
| |
1013 |
end |
| |
1014 |
|
| |
1015 |
# Define an event handler for PUT requests. |
| |
1016 |
# |
| |
1017 |
# NOTE: PUT events are triggered when the HTTP request method is |
| |
1018 |
# PUT and also when the request method is POST and the body includes a |
| |
1019 |
# "_method" parameter set to "PUT". |
| |
1020 |
def put(path, options={}, &b) |
| |
1021 |
event(:put, path, options, &b) |
| |
1022 |
end |
| |
1023 |
|
| |
1024 |
# Define an event handler for DELETE requests. |
| |
1025 |
# |
| |
1026 |
# NOTE: DELETE events are triggered when the HTTP request method is |
| |
1027 |
# DELETE and also when the request method is POST and the body includes a |
| |
1028 |
# "_method" parameter set to "DELETE". |
| |
1029 |
def delete(path, options={}, &b) |
| |
1030 |
event(:delete, path, options, &b) |
|
47aa6753
»
|
Blake Mizerany |
2008-01-16 |
Setting the env in test |
1031 |
end |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
1032 |
|
| |
1033 |
# Visits and invokes each handler registered for the +request_method+ in |
| |
1034 |
# definition order until a Result response is produced. If no handler |
| |
1035 |
# responds with a Result, the NotFound error handler is invoked. |
| |
1036 |
# |
| |
1037 |
# When the request_method is "HEAD" and no valid Result is produced by |
| |
1038 |
# the set of handlers registered for HEAD requests, an attempt is made to |
| |
1039 |
# invoke the GET handlers to generate the response before resorting to the |
| |
1040 |
# default error handler. |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
1041 |
def lookup(request) |
| |
1042 |
method = request.request_method.downcase.to_sym |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
1043 |
events[method].eject(&[:invoke, request]) || |
| |
1044 |
(events[:get].eject(&[:invoke, request]) if method == :head) || |
| |
1045 |
errors[NotFound].invoke(request) |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
1046 |
end |
|
06e2a38f
»
|
Blake Mizerany |
2007-11-29 |
options |
1047 |
|
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1048 |
|
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1049 |
# Define a named template. The template may be referenced from |
| |
1050 |
# event handlers by passing the name as a Symbol to rendering |
| |
1051 |
# methods. The block is executed each time the template is rendered |
| |
1052 |
# and the resulting object is passed to the template handler. |
| |
1053 |
# |
| |
1054 |
# The following example defines a HAML template named hello and |
| |
1055 |
# invokes it from an event handler: |
| |
1056 |
# |
| |
1057 |
# template :hello do |
| |
1058 |
# "h1 Hello World!" |
| |
1059 |
# end |
| |
1060 |
# |
| |
1061 |
# get '/' do |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1062 |
# haml :hello |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1063 |
# end |
| |
1064 |
# |
| |
1065 |
def template(name, &b) |
|
6bda16b9
»
|
Blake Mizerany |
2008-03-26 |
added `template` to DSL |
1066 |
templates[name] = b |
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
1067 |
end |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1068 |
|
| |
1069 |
# Define a layout template. |
| |
1070 |
def layout(name=:layout, &b) |
| |
1071 |
template(name, &b) |
|
4a246966
»
|
Blake Mizerany |
2007-11-29 |
Custom 404 |
1072 |
end |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1073 |
|
| |
1074 |
# Define a custom error handler for the exception class +type+. The block |
| |
1075 |
# is invoked when the specified exception type is raised from an error |
| |
1076 |
# handler and can manipulate the response as needed: |
| |
1077 |
# |
| |
1078 |
# error MyCustomError do |
| |
1079 |
# status 500 |
| |
1080 |
# 'So what happened was...' + request.env['sinatra.error'].message |
| |
1081 |
# end |
| |
1082 |
# |
| |
1083 |
# The Sinatra::ServerError handler is used by default when an exception |
| |
1084 |
# occurs and no matching error handler is found. |
| |
1085 |
def error(type=ServerError, options = {}, &b) |
| |
1086 |
errors[type] = Error.new(type, &b) |
| |
1087 |
end |
| |
1088 |
|
| |
1089 |
# Define a custom error handler for '404 Not Found' responses. This is a |
| |
1090 |
# shorthand for: |
| |
1091 |
# error NotFound do |
| |
1092 |
# .. |
| |
1093 |
# end |
| |
1094 |
def not_found(options={}, &b) |
| |
1095 |
error NotFound, options, &b |
| |
1096 |
end |
| |
1097 |
|
|
418db1ed
»
|
rtomayko |
2008-05-19 |
minor rdoc formatting fixes |
1098 |
# Define a request filter. When <tt>type</tt> is <tt>:before</tt>, execute the |
| |
1099 |
# block in the context of each request before matching event handlers. |
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1100 |
def filter(type, &b) |
| |
1101 |
filters[type] << b |
| |
1102 |
end |
| |
1103 |
|
| |
1104 |
# Invoke the block in the context of each request before invoking |
| |
1105 |
# matching event handlers. |
| |
1106 |
def before(&b) |
| |
1107 |
filter :before, &b |
|
47aa6753
»
|
Blake Mizerany |
2008-01-16 |
Setting the env in test |
1108 |
end |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
1109 |
|
|
682c7de1
»
|
Blake Mizerany |
2008-02-23 |
reload! |
1110 |
def development? |
| |
1111 |
options.env == :development |
| |
1112 |
end |
| |
1113 |
|
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1114 |
# Clear all events, templates, filters, and error handlers |
| |
1115 |
# and then reload the application source file. This occurs |
| |
1116 |
# automatically before each request is processed in development. |
|
682c7de1
»
|
Blake Mizerany |
2008-02-23 |
reload! |
1117 |
def reload! |
| |
1118 |
clearables.each(&:clear) |
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
1119 |
load_default_configuration! |
|
ce673fa4
»
|
bmizerany |
2008-05-18 |
Fixes problem in developmen... |
1120 |
@pipeline = nil |
| |
1121 |
@reloading = true |
|
174d9c8a
»
|
cschneid |
2008-05-18 |
Kernel.load $0 breaks when ... |
1122 |
Kernel.load Sinatra.options.app_file |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1123 |
@reloading = false |
|
682c7de1
»
|
Blake Mizerany |
2008-02-23 |
reload! |
1124 |
end |
|
38588af1
»
|
rtomayko |
2008-04-14 |
Refactor options / configur... |
1125 |
|
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1126 |
# Determine whether the application is in the process of being |
| |
1127 |
# reloaded. |
| |
1128 |
def reloading? |
| |
1129 |
@reloading == true |
| |
1130 |
end |
| |
1131 |
|
| |
1132 |
# Mutex instance used for thread synchronization. |
|
09ac1757
»
|
Blake Mizerany |
2008-03-15 |
Mutex |
1133 |
def mutex |
| |
1134 |
@@mutex ||= Mutex.new |
| |
1135 |
end |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1136 |
|
| |
1137 |
# Yield to the block with thread synchronization |
|
09ac1757
»
|
Blake Mizerany |
2008-03-15 |
Mutex |
1138 |
def run_safely |
| |
1139 |
if options.mutex |
| |
1140 |
mutex.synchronize { yield } |
| |
1141 |
else |
| |
1142 |
yield |
| |
1143 |
end |
| |
1144 |
end |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1145 |
|
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
1146 |
# Add a piece of Rack middleware to the pipeline leading to the |
| |
1147 |
# application. |
| |
1148 |
def use(klass, *args, &block) |
| |
1149 |
fail "#{klass} must respond to 'new'" unless klass.respond_to?(:new) |
| |
1150 |
@pipeline = nil |
| |
1151 |
@middleware.push([ klass, args, block ]).last |
| |
1152 |
end |
| |
1153 |
|
| |
1154 |
private |
| |
1155 |
|
| |
1156 |
# Rack middleware derived from current state of application options. |
| |
1157 |
# These components are plumbed in at the very beginning of the |
| |
1158 |
# pipeline. |
| |
1159 |
def optional_middleware |
| |
1160 |
[ |
| |
1161 |
([ Rack::CommonLogger, [], nil ] if options.logging), |
| |
1162 |
([ Rack::Session::Cookie, [], nil ] if options.sessions) |
| |
1163 |
].compact |
| |
1164 |
end |
| |
1165 |
|
| |
1166 |
# Rack middleware explicitly added to the application with #use. These |
| |
1167 |
# components are plumbed into the pipeline downstream from |
| |
1168 |
# #optional_middle. |
| |
1169 |
def explicit_middleware |
| |
1170 |
@middleware |
| |
1171 |
end |
| |
1172 |
|
| |
1173 |
# All Rack middleware used to construct the pipeline. |
| |
1174 |
def middleware |
| |
1175 |
optional_middleware + explicit_middleware |
| |
1176 |
end |
| |
1177 |
|
| |
1178 |
public |
| |
1179 |
|
| |
1180 |
# An assembled pipeline of Rack middleware that leads eventually to |
| |
1181 |
# the Application#invoke method. The pipeline is built upon first |
| |
1182 |
# access. Defining new middleware with Application#use or manipulating |
| |
1183 |
# application options may cause the pipeline to be rebuilt. |
| |
1184 |
def pipeline |
| |
1185 |
@pipeline ||= |
| |
1186 |
middleware.inject(method(:dispatch)) do |app,(klass,args,block)| |
| |
1187 |
klass.new(app, *args, &block) |
| |
1188 |
end |
| |
1189 |
end |
| |
1190 |
|
| |
1191 |
# Rack compatible request invocation interface. |
|
d4548542
»
|
Blake Mizerany |
2007-11-27 |
serving simple events |
1192 |
def call(env) |
|
682c7de1
»
|
Blake Mizerany |
2008-02-23 |
reload! |
1193 |
reload! if development? |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
1194 |
pipeline.call(env) |
| |
1195 |
end |
| |
1196 |
|
| |
1197 |
# Request invocation handler - called at the end of the Rack pipeline |
| |
1198 |
# for each request. |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1199 |
# |
| |
1200 |
# 1. Create Rack::Request, Rack::Response helper objects. |
| |
1201 |
# 2. Lookup event handler based on request method and path. |
| |
1202 |
# 3. Create new EventContext to house event handler evaluation. |
| |
1203 |
# 4. Invoke each #before filter in context of EventContext object. |
| |
1204 |
# 5. Invoke event handler in context of EventContext object. |
| |
1205 |
# 6. Return response to Rack. |
| |
1206 |
# |
| |
1207 |
# See the Rack specification for detailed information on the |
| |
1208 |
# +env+ argument and return value. |
|
c1aa6663
»
|
rtomayko |
2008-04-15 |
Rack pipelines leading to a... |
1209 |
def dispatch(env) |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
1210 |
request = Rack::Request.new(env) |
| |
1211 |
result = lookup(request) |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1212 |
context = EventContext.new(request, Rack::Response.new, result.params) |
|
aaed7522
»
|
Blake Mizerany |
2008-02-23 |
clean-up |
1213 |
context.status(result.status) |
|
95287a1b
»
|
Blake Mizerany |
2007-12-02 |
not needed |
1214 |
begin |
|
09ac1757
»
|
Blake Mizerany |
2008-03-15 |
Mutex |
1215 |
returned = run_safely do |
| |
1216 |
catch(:halt) do |
| |
1217 |
filters[:before].each { |f| context.instance_eval(&f) } |
| |
1218 |
[:complete, context.instance_eval(&result.block)] |
| |
1219 |
end |
|
525d99f1
»
|
Blake Mizerany |
2007-11-29 |
Custom 500's |
1220 |
end |
| |
1221 |
body = returned.to_result(context) |
| |
1222 |
rescue => e |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
1223 |
request.env['sinatra.error'] = e |
|
ba2d234c
»
|
Blake Mizerany |
2008-02-23 |
i can has error map? |
1224 |
context.status(500) |
|
0fa5de74
»
|
Blake Mizerany |
2008-03-04 |
making better use of Rack::... |
1225 |
result = (errors[e.class] || errors[ServerError]).invoke(request) |
|
09ac1757
»
|
Blake Mizerany |
2008-03-15 |
Mutex |
1226 |
returned = run_safely do |
| |
1227 |
catch(:halt) do |
| |
1228 |
[:complete, context.instance_eval(&result.block)] |
| |
1229 |
end |
|
525d99f1
»
|
Blake Mizerany |
2007-11-29 |
Custom 500's |
1230 |
end |
| |
1231 |
body = returned.to_result(context) |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1232 |
end |
|
aaed7522
»
|
Blake Mizerany |
2008-02-23 |
clean-up |
1233 |
body = '' unless body.respond_to?(:each) |
|
b47ffd39
»
|
rtomayko |
2008-03-10 |
HEAD support and Static as ... |
1234 |
body = '' if request.request_method.upcase == 'HEAD' |
|
aaed7522
»
|
Blake Mizerany |
2008-02-23 |
clean-up |
1235 |
context.body = body.kind_of?(String) ? [*body] : body |
| |
1236 |
context.finish |
|
d4548542
»
|
Blake Mizerany |
2007-11-27 |
serving simple events |
1237 |
end |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1238 |
|
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
1239 |
# Called immediately after the application is initialized or reloaded to |
| |
1240 |
# register default events, templates, and error handlers. |
| |
1241 |
def load_default_configuration! |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1242 |
|
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
1243 |
# The static event is always executed first. |
| |
1244 |
events[:get] << Static.new |
|
24139878
»
|
rtomayko |
2008-04-15 |
Finish Sinatra::Application... |
1245 |
|
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
1246 |
# Default configuration for all environments. |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1247 |
configure do |
|
0eca3f46
»
|
Blake Mizerany |
2008-04-01 |
raise errors from error |
1248 |
error do |
| |
1249 |
raise request.env['sinatra.error'] if Sinatra.options.raise_errors |
| |
1250 |
'<h1>Internal Server Error</h1>' |
| |
1251 |
end |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1252 |
not_found { '<h1>Not Found</h1>'} |
| |
1253 |
end |
| |
1254 |
|
| |
1255 |
configures :development do |
| |
1256 |
|
| |
1257 |
get '/sinatra_custom_images/:image.png' do |
| |
1258 |
File.read(File.dirname(__FILE__) + "/../images/#{params[:image]}.png") |
| |
1259 |
end |
| |
1260 |
|
| |
1261 |
not_found do |
| |
1262 |
%Q( |
|
713b66a3
»
|
Blake Mizerany |
2008-03-15 |
friendly helper |
1263 |
<style> |
| |
1264 |
body { |
| |
1265 |
text-align: center; |
| |
1266 |
color: #888; |
| |
1267 |
font-family: Arial; |
| |
1268 |
font-size: 22px; |
| |
1269 |
margin: 20px; |
| |
1270 |
} |
| |
1271 |
#content { |
| |
1272 |
margin: 0 auto; |
| |
1273 |
width: 500px; |
| |
1274 |
text-align: left; |
| |
1275 |
} |
| |
1276 |
</style> |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1277 |
<html> |
|
713b66a3
»
|
Blake Mizerany |
2008-03-15 |
friendly helper |
1278 |
<body> |
| |
1279 |
<h2>Sinatra doesn't know this diddy.</h2> |
| |
1280 |
<img src='/sinatra_custom_images/404.png'></img> |
| |
1281 |
<div id="content"> |
| |
1282 |
Try this: |
| |
1283 |
<pre>#{request.request_method.downcase} "#{request.path_info}" do |
| |
1284 |
.. do something .. |
| |
1285 |
end<pre> |
| |
1286 |
</div> |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1287 |
</body> |
| |
1288 |
</html> |
| |
1289 |
) |
| |
1290 |
end |
| |
1291 |
|
| |
1292 |
error do |
| |
1293 |
@error = request.env['sinatra.error'] |
| |
1294 |
%Q( |
| |
1295 |
<html> |
| |
1296 |
<body> |
| |
1297 |
<style type="text/css" media="screen"> |
| |
1298 |
body { |
| |
1299 |
font-family: Verdana; |
| |
1300 |
color: #333; |
| |
1301 |
} |
| |
1302 |
|
| |
1303 |
#content { |
| |
1304 |
width: 700px; |
| |
1305 |
margin-left: 20px; |
| |
1306 |
} |
| |
1307 |
|
| |
1308 |
#content h1 { |
| |
1309 |
width: 99%; |
| |
1310 |
color: #1D6B8D; |
| |
1311 |
font-weight: bold; |
| |
1312 |
} |
| |
1313 |
|
| |
1314 |
#stacktrace { |
| |
1315 |
margin-top: -20px; |
| |
1316 |
} |
| |
1317 |
|
| |
1318 |
#stacktrace pre { |
| |
1319 |
font-size: 12px; |
| |
1320 |
border-left: 2px solid #ddd; |
| |
1321 |
padding-left: 10px; |
| |
1322 |
} |
| |
1323 |
|
| |
1324 |
#stacktrace img { |
| |
1325 |
margin-top: 10px; |
| |
1326 |
} |
| |
1327 |
</style> |
| |
1328 |
<div id="content"> |
| |
1329 |
<img src="/sinatra_custom_images/500.png" /> |
|
5f3eac03
»
|
Blake Mizerany |
2008-03-15 |
Better errors |
1330 |
<div class="info"> |
| |
1331 |
Params: <pre>#{params.inspect} |
| |
1332 |
</div> |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1333 |
<div id="stacktrace"> |
|
5f3eac03
»
|
Blake Mizerany |
2008-03-15 |
Better errors |
1334 |
<h1>#{Rack::Utils.escape_html(@error.class.name + ' - ' + @error.message)}</h1> |
|
327c6ece
»
|
rtomayko |
2008-03-08 |
Fix that built-in error mes... |
1335 |
<pre><code>#{Rack::Utils.escape_html(@error.backtrace.join("\n"))}</code></pre> |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1336 |
</div> |
| |
1337 |
</body> |
| |
1338 |
</html> |
| |
1339 |
) |
| |
1340 |
end |
| |
1341 |
end |
| |
1342 |
end |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1343 |
|
|
a54d7cc3
»
|
rtomayko |
2008-04-15 |
Move Environment.setup! int... |
1344 |
private :load_default_configuration! |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1345 |
|
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1346 |
end |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1347 |
|
| |
1348 |
end |
| |
1349 |
|
|
da3439af
»
|
rtomayko |
2008-04-14 |
Sinatra::Application as a s... |
1350 |
# Delegate DSLish methods to the currently active Sinatra::Application |
| |
1351 |
# instance. |
| |
1352 |
Sinatra::Application::FORWARD_METHODS.each do |method| |
| |
1353 |
eval(<<-EOS, binding, '(__DSL__)', 1) |
| |
1354 |
def #{method}(*args, &b) |
| |
1355 |
Sinatra.application.#{method}(*args, &b) |
| |
1356 |
end |
| |
1357 |
EOS |
|
47aa6753
»
|
Blake Mizerany |
2008-01-16 |
Setting the env in test |
1358 |
end |
| |
1359 |
|
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1360 |
def helpers(&b) |
| |
1361 |
Sinatra::EventContext.class_eval(&b) |
| |
1362 |
end |
| |
1363 |
|
|
d874133b
»
|
Blake Mizerany |
2008-03-26 |
inline templates! |
1364 |
def use_in_file_templates! |
| |
1365 |
require 'stringio' |
| |
1366 |
templates = IO.read(caller.first.split(':').first).split('__FILE__').last |
| |
1367 |
data = StringIO.new(templates) |
| |
1368 |
current_template = nil |
| |
1369 |
data.each do |line| |
|
1987e550
»
|
Blake Mizerany |
2008-04-26 |
New standard: use_in_file_... |
1370 |
if line =~ /^@@\s?(.*)/ |
|
d874133b
»
|
Blake Mizerany |
2008-03-26 |
inline templates! |
1371 |
current_template = $1.to_sym |
| |
1372 |
Sinatra.application.templates[current_template] = '' |
| |
1373 |
elsif current_template |
| |
1374 |
Sinatra.application.templates[current_template] << line |
| |
1375 |
end |
| |
1376 |
end |
| |
1377 |
end |
| |
1378 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
1379 |
def mime(ext, type) |
| |
1380 |
Rack::File::MIME_TYPES[ext.to_s] = type |
| |
1381 |
end |
| |
1382 |
|
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1383 |
### Misc Core Extensions |
| |
1384 |
|
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1385 |
module Kernel |
| |
1386 |
|
| |
1387 |
def silence_warnings |
| |
1388 |
old_verbose, $VERBOSE = $VERBOSE, nil |
| |
1389 |
yield |
| |
1390 |
ensure |
| |
1391 |
$VERBOSE = old_verbose |
| |
1392 |
end |
| |
1393 |
|
| |
1394 |
end |
| |
1395 |
|
| |
1396 |
class String |
| |
1397 |
|
| |
1398 |
# Converts +self+ to an escaped URI parameter value |
| |
1399 |
# 'Foo Bar'.to_param # => 'Foo%20Bar' |
| |
1400 |
def to_param |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
1401 |
Rack::Utils.escape(self) |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1402 |
end |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
1403 |
alias :http_escape :to_param |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1404 |
|
| |
1405 |
# Converts +self+ from an escaped URI parameter value |
| |
1406 |
# 'Foo%20Bar'.from_param # => 'Foo Bar' |
| |
1407 |
def from_param |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
1408 |
Rack::Utils.unescape(self) |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1409 |
end |
|
d16ee653
»
|
Blake Mizerany |
2008-04-26 |
fixed escaped paths not res... |
1410 |
alias :http_unescape :from_param |
|
18d3c871
»
|
Blake Mizerany |
2007-11-27 |
more tests |
1411 |
|
| |
1412 |
end |
| |
1413 |
|
| |
1414 |
class Hash |
| |
1415 |
|
| |
1416 |
def to_params |
| |
1417 |
map { |k,v| "#{k}=#{URI.escape(v)}" }.join('&') |
| |
1418 |
end |
| |
1419 |
|
| |
1420 |
def symbolize_keys |
| |
1421 |
self.inject({}) { |h,(k,v)| h[k.to_sym] = v; h } |
| |
1422 |
end |
| |
1423 |
|
| |
1424 |
def pass(*keys) |
| |
1425 |
reject { |k,v| !keys.include?(k) } |
| |
1426 |
end |
| |
1427 |
|
| |
1428 |
end |
| |
1429 |
|
| |
1430 |
class Symbol |
| |
1431 |
|
| |
1432 |
def to_proc |
| |
1433 |
Proc.new { |*args| args.shift.__send__(self, *args) } |
| |
1434 |
end |
| |
1435 |
|
| |
1436 |
end |
| |
1437 |
|
| |
1438 |
class Array |
| |
1439 |
|
| |
1440 |
def to_hash |
| |
1441 |
self.inject({}) { |h, (k, v)| h[k] = v; h } |
| |
1442 |
end |
| |
1443 |
|
| |
1444 |
def to_proc |
| |
1445 |
Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) } |
| |
1446 |
end |
| |
1447 |
|
| |
1448 |
end |
| |
1449 |
|
| |
1450 |
module Enumerable |
| |
1451 |
|
| |
1452 |
def eject(&block) |
| |
1453 |
find { |e| result = block[e] and break result } |
| |
1454 |
end |
| |
1455 |
|
| |
1456 |
end |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1457 |
|
| |
1458 |
### Core Extension results for throw :halt |
| |
1459 |
|
| |
1460 |
class Proc |
| |
1461 |
def to_result(cx, *args) |
| |
1462 |
cx.instance_eval(&self) |
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
1463 |
args.shift.to_result(cx, *args) |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1464 |
end |
| |
1465 |
end |
| |
1466 |
|
| |
1467 |
class String |
| |
1468 |
def to_result(cx, *args) |
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
1469 |
args.shift.to_result(cx, *args) |
| |
1470 |
self |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1471 |
end |
| |
1472 |
end |
| |
1473 |
|
| |
1474 |
class Array |
| |
1475 |
def to_result(cx, *args) |
| |
1476 |
self.shift.to_result(cx, *self) |
| |
1477 |
end |
| |
1478 |
end |
| |
1479 |
|
| |
1480 |
class Symbol |
| |
1481 |
def to_result(cx, *args) |
| |
1482 |
cx.send(self, *args) |
| |
1483 |
end |
| |
1484 |
end |
| |
1485 |
|
| |
1486 |
class Fixnum |
| |
1487 |
def to_result(cx, *args) |
| |
1488 |
cx.status self |
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
1489 |
args.shift.to_result(cx, *args) |
|
d9cad760
»
|
Blake Mizerany |
2007-11-28 |
throw :halt |
1490 |
end |
| |
1491 |
end |
|
b72f00cc
»
|
Blake Mizerany |
2007-11-28 |
this should be stop and bod... |
1492 |
|
| |
1493 |
class NilClass |
| |
1494 |
def to_result(cx, *args) |
|
1f204991
»
|
Blake Mizerany |
2008-03-24 |
getting mare advanced with ... |
1495 |
'' |
|
b72f00cc
»
|
Blake Mizerany |
2007-11-28 |
this should be stop and bod... |
1496 |
end |
| |
1497 |
end |
| |
1498 |
|
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
1499 |
at_exit do |
|
bd8515bb
»
|
Blake Mizerany |
2007-11-29 |
Notify user of error if DSL... |
1500 |
raise $! if $! |
|
5a61c3be
»
|
Blake Mizerany |
2008-02-24 |
FIX: reloading configs |
1501 |
if Sinatra.application.options.run |
| |
1502 |
Sinatra.run |
| |
1503 |
end |
|
703cf3b2
»
|
Blake Mizerany |
2007-11-28 |
now running |
1504 |
end |
|
9ee50b30
»
|
Blake Mizerany |
2007-11-29 |
* Default error messages |
1505 |
|
|
fbdf982f
»
|
Blake Mizerany |
2008-02-24 |
Streaming |
1506 |
mime :xml, 'application/xml' |
| |
1507 |
mime :js, 'application/javascript' |