sinatra 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGES +21 -0
- data/README.de.md +109 -111
- data/README.hu.md +1 -1
- data/README.md +4 -4
- data/README.pt-br.md +4 -4
- data/lib/sinatra/base.rb +318 -316
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +1 -1
- data/test/helpers_test.rb +1 -0
- data/test/request_test.rb +1 -0
- data/test/routing_test.rb +10 -0
- metadata +12 -31
data/README.hu.md
CHANGED
@@ -343,7 +343,7 @@ kérés alkalmával kiértékelődnek, így módosíthatják a kérést és a
|
|
343
343
|
választ egyaránt. A szűrőkbe felvett példányváltozók elérhetőek lesznek
|
344
344
|
az útvonalakban és a sablonokban is:
|
345
345
|
|
346
|
-
```
|
346
|
+
```ruby
|
347
347
|
before do
|
348
348
|
@note = 'Csá!'
|
349
349
|
request.path_info = '/foo/bar/baz'
|
data/README.md
CHANGED
@@ -2093,18 +2093,18 @@ set :protection, :session => true
|
|
2093
2093
|
</dd>
|
2094
2094
|
|
2095
2095
|
<dt>running</dt>
|
2096
|
-
<dd>is the built-in server running now?
|
2096
|
+
<dd>is the built-in server running now? Do not change this setting!</dd>
|
2097
2097
|
|
2098
2098
|
<dt>server</dt>
|
2099
2099
|
<dd>
|
2100
|
-
Server or list of servers to use for built-in server.
|
2101
|
-
default depends on Ruby implementation.
|
2100
|
+
Server or list of servers to use for built-in server. Order indicates
|
2101
|
+
priority, default depends on Ruby implementation.
|
2102
2102
|
</dd>
|
2103
2103
|
|
2104
2104
|
<dt>sessions</dt>
|
2105
2105
|
<dd>
|
2106
2106
|
Enable cookie-based sessions support using <tt>Rack::Session::Cookie</tt>.
|
2107
|
-
|
2107
|
+
See 'Using Sessions' section for more information.
|
2108
2108
|
</dd>
|
2109
2109
|
|
2110
2110
|
<dt>show_exceptions</dt>
|
data/README.pt-br.md
CHANGED
@@ -16,7 +16,7 @@ get '/' do
|
|
16
16
|
end
|
17
17
|
```
|
18
18
|
|
19
|
-
Instale a gem e execute
|
19
|
+
Instale a gem e execute o arquivo criado acima:
|
20
20
|
|
21
21
|
``` shell
|
22
22
|
gem install sinatra
|
@@ -25,8 +25,8 @@ ruby minhaapp.rb
|
|
25
25
|
|
26
26
|
Acesse em: [localhost:4567](http://localhost:4567)
|
27
27
|
|
28
|
-
Recomendamos a execução de `gem install thin`. Caso esteja disponível, o
|
29
|
-
Sinatra irá
|
28
|
+
Recomendamos a execução de `gem install thin`. Caso esta gem esteja disponível, o
|
29
|
+
Sinatra irá utilizá-la.
|
30
30
|
|
31
31
|
## Rotas
|
32
32
|
|
@@ -59,7 +59,7 @@ options '/' do
|
|
59
59
|
end
|
60
60
|
```
|
61
61
|
|
62
|
-
As rotas são interpretadas na ordem em que são
|
62
|
+
As rotas são interpretadas na ordem em que são definidas. A primeira
|
63
63
|
rota encontrada responde ao pedido.
|
64
64
|
|
65
65
|
Padrões de rota podem conter parâmetros nomeados, acessível através do
|
data/lib/sinatra/base.rb
CHANGED
@@ -27,6 +27,10 @@ module Sinatra
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def accept?(type)
|
31
|
+
preferred_type.include?(type)
|
32
|
+
end
|
33
|
+
|
30
34
|
def preferred_type(*types)
|
31
35
|
accepts = accept # just evaluate once
|
32
36
|
return accepts.first if types.empty?
|
@@ -38,7 +42,6 @@ module Sinatra
|
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
41
|
-
alias accept? preferred_type
|
42
45
|
alias secure? ssl?
|
43
46
|
|
44
47
|
def forwarded?
|
@@ -106,7 +109,7 @@ module Sinatra
|
|
106
109
|
end
|
107
110
|
end
|
108
111
|
|
109
|
-
# The response object. See Rack::Response and Rack::
|
112
|
+
# The response object. See Rack::Response and Rack::Response::Helpers for
|
110
113
|
# more info:
|
111
114
|
# http://rack.rubyforge.org/doc/classes/Rack/Response.html
|
112
115
|
# http://rack.rubyforge.org/doc/classes/Rack/Response/Helpers.html
|
@@ -756,6 +759,7 @@ module Sinatra
|
|
756
759
|
end
|
757
760
|
|
758
761
|
private
|
762
|
+
|
759
763
|
# logic shared between builder and nokogiri
|
760
764
|
def render_ruby(engine, template, options = {}, locals = {}, &block)
|
761
765
|
options, template = template, nil if template.is_a?(Hash)
|
@@ -849,7 +853,9 @@ module Sinatra
|
|
849
853
|
include Helpers
|
850
854
|
include Templates
|
851
855
|
|
852
|
-
|
856
|
+
URI = ::URI.const_defined?(:Parser) ? ::URI::Parser.new : ::URI
|
857
|
+
|
858
|
+
attr_accessor :app, :env, :request, :response, :params
|
853
859
|
attr_reader :template_cache
|
854
860
|
|
855
861
|
def initialize(app = nil)
|
@@ -864,8 +870,6 @@ module Sinatra
|
|
864
870
|
dup.call!(env)
|
865
871
|
end
|
866
872
|
|
867
|
-
attr_accessor :env, :request, :response, :params
|
868
|
-
|
869
873
|
def call!(env) # :nodoc:
|
870
874
|
@env = env
|
871
875
|
@request = Request.new(env)
|
@@ -929,191 +933,210 @@ module Sinatra
|
|
929
933
|
nil
|
930
934
|
end
|
931
935
|
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
filter!
|
936
|
-
|
937
|
-
|
936
|
+
private
|
937
|
+
|
938
|
+
# Run filters defined on the class and all superclasses.
|
939
|
+
def filter!(type, base = settings)
|
940
|
+
filter! type, base.superclass if base.superclass.respond_to?(:filters)
|
941
|
+
base.filters[type].each { |args| process_route(*args) }
|
942
|
+
end
|
938
943
|
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
944
|
+
# Run routes defined on the class and all superclasses.
|
945
|
+
def route!(base = settings, pass_block = nil)
|
946
|
+
if routes = base.routes[@request.request_method]
|
947
|
+
routes.each do |pattern, keys, conditions, block|
|
948
|
+
pass_block = process_route(pattern, keys, conditions) do |*args|
|
949
|
+
env['sinatra.route'] = block.instance_variable_get(:@route_name)
|
950
|
+
route_eval { block[*args] }
|
951
|
+
end
|
945
952
|
end
|
946
953
|
end
|
947
|
-
end
|
948
954
|
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
955
|
+
# Run routes defined in superclass.
|
956
|
+
if base.superclass.respond_to?(:routes)
|
957
|
+
return route!(base.superclass, pass_block)
|
958
|
+
end
|
953
959
|
|
954
|
-
|
955
|
-
|
956
|
-
|
960
|
+
route_eval(&pass_block) if pass_block
|
961
|
+
route_missing
|
962
|
+
end
|
957
963
|
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
964
|
+
# Run a route block and throw :halt with the result.
|
965
|
+
def route_eval
|
966
|
+
throw :halt, yield
|
967
|
+
end
|
962
968
|
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
969
|
+
# If the current request matches pattern and conditions, fill params
|
970
|
+
# with keys and call the given block.
|
971
|
+
# Revert params afterwards.
|
972
|
+
#
|
973
|
+
# Returns pass block.
|
974
|
+
def process_route(pattern, keys, conditions, block = nil, values = [])
|
975
|
+
route = @request.path_info
|
976
|
+
route = '/' if route.empty? and not settings.empty_path_info?
|
977
|
+
return unless match = pattern.match(route)
|
978
|
+
values += match.captures.to_a.map { |v| force_encoding URI.unescape(v) if v }
|
973
979
|
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
980
|
+
if values.any?
|
981
|
+
original, @params = params, params.merge('splat' => [], 'captures' => values)
|
982
|
+
keys.zip(values) { |k,v| Array === @params[k] ? @params[k] << v : @params[k] = v if v }
|
983
|
+
end
|
978
984
|
|
979
|
-
|
980
|
-
|
981
|
-
|
985
|
+
catch(:pass) do
|
986
|
+
conditions.each { |c| throw :pass if c.bind(self).call == false }
|
987
|
+
block ? block[self, values] : yield(self, values)
|
988
|
+
end
|
989
|
+
ensure
|
990
|
+
@params = original if original
|
982
991
|
end
|
983
|
-
ensure
|
984
|
-
@params = original if original
|
985
|
-
end
|
986
992
|
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
993
|
+
# No matching route was found or all routes passed. The default
|
994
|
+
# implementation is to forward the request downstream when running
|
995
|
+
# as middleware (@app is non-nil); when no downstream app is set, raise
|
996
|
+
# a NotFound exception. Subclasses can override this method to perform
|
997
|
+
# custom route miss logic.
|
998
|
+
def route_missing
|
999
|
+
if @app
|
1000
|
+
forward
|
1001
|
+
else
|
1002
|
+
raise NotFound
|
1003
|
+
end
|
997
1004
|
end
|
998
|
-
end
|
999
|
-
|
1000
|
-
# Attempt to serve static files from public directory. Throws :halt when
|
1001
|
-
# a matching file is found, returns nil otherwise.
|
1002
|
-
def static!
|
1003
|
-
return if (public_dir = settings.public_folder).nil?
|
1004
|
-
public_dir = File.expand_path(public_dir)
|
1005
1005
|
|
1006
|
-
|
1007
|
-
|
1006
|
+
# Attempt to serve static files from public directory. Throws :halt when
|
1007
|
+
# a matching file is found, returns nil otherwise.
|
1008
|
+
def static!
|
1009
|
+
return if (public_dir = settings.public_folder).nil?
|
1010
|
+
public_dir = File.expand_path(public_dir)
|
1008
1011
|
|
1009
|
-
|
1010
|
-
|
1011
|
-
send_file path, :disposition => nil
|
1012
|
-
end
|
1012
|
+
path = File.expand_path(public_dir + unescape(request.path_info))
|
1013
|
+
return unless path.start_with?(public_dir) and File.file?(path)
|
1013
1014
|
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
when Hash
|
1018
|
-
new_hash = indifferent_hash
|
1019
|
-
object.each { |key, value| new_hash[key] = indifferent_params(value) }
|
1020
|
-
new_hash
|
1021
|
-
when Array
|
1022
|
-
object.map { |item| indifferent_params(item) }
|
1023
|
-
else
|
1024
|
-
object
|
1015
|
+
env['sinatra.static_file'] = path
|
1016
|
+
cache_control(*settings.static_cache_control) if settings.static_cache_control?
|
1017
|
+
send_file path, :disposition => nil
|
1025
1018
|
end
|
1026
|
-
end
|
1027
1019
|
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1020
|
+
# Enable string or symbol key access to the nested params hash.
|
1021
|
+
def indifferent_params(object)
|
1022
|
+
case object
|
1023
|
+
when Hash
|
1024
|
+
new_hash = indifferent_hash
|
1025
|
+
object.each { |key, value| new_hash[key] = indifferent_params(value) }
|
1026
|
+
new_hash
|
1027
|
+
when Array
|
1028
|
+
object.map { |item| indifferent_params(item) }
|
1029
|
+
else
|
1030
|
+
object
|
1031
|
+
end
|
1032
|
+
end
|
1032
1033
|
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
if Array === res and Fixnum === res.first
|
1038
|
-
res = res.dup
|
1039
|
-
status(res.shift)
|
1040
|
-
body(res.pop)
|
1041
|
-
headers(*res)
|
1042
|
-
elsif res.respond_to? :each
|
1043
|
-
body res
|
1044
|
-
end
|
1045
|
-
nil # avoid double setting the same response tuple twice
|
1046
|
-
end
|
1034
|
+
# Creates a Hash with indifferent access.
|
1035
|
+
def indifferent_hash
|
1036
|
+
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
1037
|
+
end
|
1047
1038
|
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1039
|
+
# Run the block with 'throw :halt' support and apply result to the response.
|
1040
|
+
def invoke
|
1041
|
+
res = catch(:halt) { yield }
|
1042
|
+
res = [res] if Fixnum === res or String === res
|
1043
|
+
if Array === res and Fixnum === res.first
|
1044
|
+
res = res.dup
|
1045
|
+
status(res.shift)
|
1046
|
+
body(res.pop)
|
1047
|
+
headers(*res)
|
1048
|
+
elsif res.respond_to? :each
|
1049
|
+
body res
|
1050
|
+
end
|
1051
|
+
nil # avoid double setting the same response tuple twice
|
1054
1052
|
end
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1053
|
+
|
1054
|
+
# Dispatch a request with error handling.
|
1055
|
+
def dispatch!
|
1056
|
+
invoke do
|
1057
|
+
static! if settings.static? && (request.get? || request.head?)
|
1058
|
+
filter! :before
|
1059
|
+
route!
|
1060
|
+
end
|
1060
1061
|
rescue ::Exception => boom
|
1061
|
-
invoke { handle_exception!(boom) }
|
1062
|
+
invoke { handle_exception!(boom) }
|
1063
|
+
ensure
|
1064
|
+
begin
|
1065
|
+
filter! :after unless env['sinatra.static_file']
|
1066
|
+
rescue ::Exception => boom
|
1067
|
+
invoke { handle_exception!(boom) } unless @env['sinatra.error']
|
1068
|
+
end
|
1062
1069
|
end
|
1063
|
-
end
|
1064
1070
|
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1071
|
+
# Error handling during requests.
|
1072
|
+
def handle_exception!(boom)
|
1073
|
+
@env['sinatra.error'] = boom
|
1068
1074
|
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1075
|
+
if boom.respond_to? :http_status
|
1076
|
+
status(boom.http_status)
|
1077
|
+
elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400, 599
|
1078
|
+
status(boom.code)
|
1079
|
+
else
|
1080
|
+
status(500)
|
1081
|
+
end
|
1076
1082
|
|
1077
|
-
|
1083
|
+
status(500) unless status.between? 400, 599
|
1078
1084
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1085
|
+
if server_error?
|
1086
|
+
dump_errors! boom if settings.dump_errors?
|
1087
|
+
raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler
|
1088
|
+
end
|
1083
1089
|
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1090
|
+
if not_found?
|
1091
|
+
headers['X-Cascade'] = 'pass' if settings.x_cascade?
|
1092
|
+
body '<h1>Not Found</h1>'
|
1093
|
+
end
|
1088
1094
|
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1095
|
+
res = error_block!(boom.class, boom) || error_block!(status, boom)
|
1096
|
+
return res if res or not server_error?
|
1097
|
+
raise boom if settings.raise_errors? or settings.show_exceptions?
|
1098
|
+
error_block! Exception, boom
|
1099
|
+
end
|
1094
1100
|
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1101
|
+
# Find an custom error block for the key(s) specified.
|
1102
|
+
def error_block!(key, *block_params)
|
1103
|
+
base = settings
|
1104
|
+
while base.respond_to?(:errors)
|
1105
|
+
next base = base.superclass unless args_array = base.errors[key]
|
1106
|
+
args_array.reverse_each do |args|
|
1107
|
+
first = args == args_array.first
|
1108
|
+
args += [block_params]
|
1109
|
+
resp = process_route(*args)
|
1110
|
+
return resp unless resp.nil? && !first
|
1111
|
+
end
|
1105
1112
|
end
|
1113
|
+
return false unless key.respond_to? :superclass and key.superclass < Exception
|
1114
|
+
error_block!(key.superclass, *block_params)
|
1106
1115
|
end
|
1107
|
-
return false unless key.respond_to? :superclass and key.superclass < Exception
|
1108
|
-
error_block!(key.superclass, *block_params)
|
1109
|
-
end
|
1110
1116
|
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1117
|
+
def dump_errors!(boom)
|
1118
|
+
msg = ["#{boom.class} - #{boom.message}:", *boom.backtrace].join("\n\t")
|
1119
|
+
@env['rack.errors'].puts(msg)
|
1120
|
+
end
|
1115
1121
|
|
1116
1122
|
class << self
|
1123
|
+
CALLERS_TO_IGNORE = [ # :nodoc:
|
1124
|
+
/\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
|
1125
|
+
/lib\/tilt.*\.rb$/, # all tilt code
|
1126
|
+
/^\(.*\)$/, # generated code
|
1127
|
+
/rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks
|
1128
|
+
/active_support/, # active_support require hacks
|
1129
|
+
/bundler(\/runtime)?\.rb/, # bundler require hacks
|
1130
|
+
/<internal:/, # internal in ruby >= 1.9.2
|
1131
|
+
/src\/kernel\/bootstrap\/[A-Z]/ # maglev kernel files
|
1132
|
+
]
|
1133
|
+
|
1134
|
+
# contrary to what the comment said previously, rubinius never supported this
|
1135
|
+
if defined?(RUBY_IGNORE_CALLERS)
|
1136
|
+
warn "RUBY_IGNORE_CALLERS is deprecated and will no longer be supported by Sinatra 2.0"
|
1137
|
+
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS)
|
1138
|
+
end
|
1139
|
+
|
1117
1140
|
attr_reader :routes, :filters, :templates, :errors
|
1118
1141
|
|
1119
1142
|
# Removes all routes, filters, middleware and extension hooks from the
|
@@ -1315,7 +1338,131 @@ module Sinatra
|
|
1315
1338
|
public_folder
|
1316
1339
|
end
|
1317
1340
|
|
1318
|
-
|
1341
|
+
# Defining a `GET` handler also automatically defines
|
1342
|
+
# a `HEAD` handler.
|
1343
|
+
def get(path, opts = {}, &block)
|
1344
|
+
conditions = @conditions.dup
|
1345
|
+
route('GET', path, opts, &block)
|
1346
|
+
|
1347
|
+
@conditions = conditions
|
1348
|
+
route('HEAD', path, opts, &block)
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
def put(path, opts = {}, &bk) route 'PUT', path, opts, &bk end
|
1352
|
+
def post(path, opts = {}, &bk) route 'POST', path, opts, &bk end
|
1353
|
+
def delete(path, opts = {}, &bk) route 'DELETE', path, opts, &bk end
|
1354
|
+
def head(path, opts = {}, &bk) route 'HEAD', path, opts, &bk end
|
1355
|
+
def options(path, opts = {}, &bk) route 'OPTIONS', path, opts, &bk end
|
1356
|
+
def patch(path, opts = {}, &bk) route 'PATCH', path, opts, &bk end
|
1357
|
+
def link(path, opts = {}, &bk) route 'LINK', path, opts, &bk end
|
1358
|
+
def unlink(path, opts = {}, &bk) route 'UNLINK', path, opts, &bk end
|
1359
|
+
|
1360
|
+
# Makes the methods defined in the block and in the Modules given
|
1361
|
+
# in `extensions` available to the handlers and templates
|
1362
|
+
def helpers(*extensions, &block)
|
1363
|
+
class_eval(&block) if block_given?
|
1364
|
+
include(*extensions) if extensions.any?
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
# Register an extension. Alternatively take a block from which an
|
1368
|
+
# extension will be created and registered on the fly.
|
1369
|
+
def register(*extensions, &block)
|
1370
|
+
extensions << Module.new(&block) if block_given?
|
1371
|
+
@extensions += extensions
|
1372
|
+
extensions.each do |extension|
|
1373
|
+
extend extension
|
1374
|
+
extension.registered(self) if extension.respond_to?(:registered)
|
1375
|
+
end
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
def development?; environment == :development end
|
1379
|
+
def production?; environment == :production end
|
1380
|
+
def test?; environment == :test end
|
1381
|
+
|
1382
|
+
# Set configuration options for Sinatra and/or the app.
|
1383
|
+
# Allows scoping of settings for certain environments.
|
1384
|
+
def configure(*envs, &block)
|
1385
|
+
yield self if envs.empty? || envs.include?(environment.to_sym)
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
# Use the specified Rack middleware
|
1389
|
+
def use(middleware, *args, &block)
|
1390
|
+
@prototype = nil
|
1391
|
+
@middleware << [middleware, args, block]
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
def quit!(server, handler_name)
|
1395
|
+
# Use Thin's hard #stop! if available, otherwise just #stop.
|
1396
|
+
server.respond_to?(:stop!) ? server.stop! : server.stop
|
1397
|
+
$stderr.puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
# Run the Sinatra app as a self-hosted server using
|
1401
|
+
# Thin, Puma, Mongrel, or WEBrick (in that order). If given a block, will call
|
1402
|
+
# with the constructed handler once we have taken the stage.
|
1403
|
+
def run!(options = {})
|
1404
|
+
set options
|
1405
|
+
handler = detect_rack_handler
|
1406
|
+
handler_name = handler.name.gsub(/.*::/, '')
|
1407
|
+
server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
|
1408
|
+
handler.run self, server_settings.merge(:Port => port, :Host => bind) do |server|
|
1409
|
+
unless handler_name =~ /cgi/i
|
1410
|
+
$stderr.puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
|
1411
|
+
"on #{port} for #{environment} with backup from #{handler_name}"
|
1412
|
+
end
|
1413
|
+
[:INT, :TERM].each { |sig| trap(sig) { quit!(server, handler_name) } }
|
1414
|
+
server.threaded = settings.threaded if server.respond_to? :threaded=
|
1415
|
+
set :running, true
|
1416
|
+
yield server if block_given?
|
1417
|
+
end
|
1418
|
+
rescue Errno::EADDRINUSE
|
1419
|
+
$stderr.puts "== Someone is already performing on port #{port}!"
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
# The prototype instance used to process requests.
|
1423
|
+
def prototype
|
1424
|
+
@prototype ||= new
|
1425
|
+
end
|
1426
|
+
|
1427
|
+
# Create a new instance without middleware in front of it.
|
1428
|
+
alias new! new unless method_defined? :new!
|
1429
|
+
|
1430
|
+
# Create a new instance of the class fronted by its middleware
|
1431
|
+
# pipeline. The object is guaranteed to respond to #call but may not be
|
1432
|
+
# an instance of the class new was called on.
|
1433
|
+
def new(*args, &bk)
|
1434
|
+
instance = new!(*args, &bk)
|
1435
|
+
Wrapper.new(build(instance).to_app, instance)
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
# Creates a Rack::Builder instance with all the middleware set up and
|
1439
|
+
# the given +app+ as end point.
|
1440
|
+
def build(app)
|
1441
|
+
builder = Rack::Builder.new
|
1442
|
+
setup_default_middleware builder
|
1443
|
+
setup_middleware builder
|
1444
|
+
builder.run app
|
1445
|
+
builder
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
def call(env)
|
1449
|
+
synchronize { prototype.call(env) }
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
# Like Kernel#caller but excluding certain magic entries and without
|
1453
|
+
# line / method information; the resulting array contains filenames only.
|
1454
|
+
def caller_files
|
1455
|
+
cleaned_caller(1).flatten
|
1456
|
+
end
|
1457
|
+
|
1458
|
+
# Like caller_files, but containing Arrays rather than strings with the
|
1459
|
+
# first element being the file, and the second being the line.
|
1460
|
+
def caller_locations
|
1461
|
+
cleaned_caller 2
|
1462
|
+
end
|
1463
|
+
|
1464
|
+
private
|
1465
|
+
|
1319
1466
|
# Dynamically defines a method on settings.
|
1320
1467
|
def define_singleton(name, content = Proc.new)
|
1321
1468
|
# replace with call to singleton_class once we're 1.9 only
|
@@ -1361,27 +1508,6 @@ module Sinatra
|
|
1361
1508
|
end
|
1362
1509
|
end
|
1363
1510
|
|
1364
|
-
public
|
1365
|
-
# Defining a `GET` handler also automatically defines
|
1366
|
-
# a `HEAD` handler.
|
1367
|
-
def get(path, opts = {}, &block)
|
1368
|
-
conditions = @conditions.dup
|
1369
|
-
route('GET', path, opts, &block)
|
1370
|
-
|
1371
|
-
@conditions = conditions
|
1372
|
-
route('HEAD', path, opts, &block)
|
1373
|
-
end
|
1374
|
-
|
1375
|
-
def put(path, opts = {}, &bk) route 'PUT', path, opts, &bk end
|
1376
|
-
def post(path, opts = {}, &bk) route 'POST', path, opts, &bk end
|
1377
|
-
def delete(path, opts = {}, &bk) route 'DELETE', path, opts, &bk end
|
1378
|
-
def head(path, opts = {}, &bk) route 'HEAD', path, opts, &bk end
|
1379
|
-
def options(path, opts = {}, &bk) route 'OPTIONS', path, opts, &bk end
|
1380
|
-
def patch(path, opts = {}, &bk) route 'PATCH', path, opts, &bk end
|
1381
|
-
def link(path, opts = {}, &bk) route 'LINK', path, opts, &bk end
|
1382
|
-
def unlink(path, opts = {}, &bk) route 'UNLINK', path, opts, &bk end
|
1383
|
-
|
1384
|
-
private
|
1385
1511
|
def route(verb, path, options = {}, &block)
|
1386
1512
|
# Because of self.options.host
|
1387
1513
|
host_name(options.delete(:host)) if options.key?(:host)
|
@@ -1410,27 +1536,30 @@ module Sinatra
|
|
1410
1536
|
pattern, keys = compile path
|
1411
1537
|
conditions, @conditions = @conditions, []
|
1412
1538
|
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1539
|
+
wrapper = block.arity != 0 ?
|
1540
|
+
proc { |a,p| unbound_method.bind(a).call(*p) } :
|
1541
|
+
proc { |a,p| unbound_method.bind(a).call }
|
1542
|
+
wrapper.instance_variable_set(:@route_name, method_name)
|
1543
|
+
|
1544
|
+
[ pattern, keys, conditions, wrapper ]
|
1416
1545
|
end
|
1417
1546
|
|
1418
1547
|
def compile(path)
|
1419
1548
|
if path.respond_to? :to_str
|
1420
1549
|
keys = []
|
1421
|
-
|
1550
|
+
|
1422
1551
|
# We append a / at the end if there was one.
|
1423
1552
|
# Reason: Splitting does not split off an empty
|
1424
1553
|
# string at the end if the split separator
|
1425
1554
|
# is at the end.
|
1426
1555
|
#
|
1427
1556
|
postfix = '/' if path =~ /\/\z/
|
1428
|
-
|
1557
|
+
|
1429
1558
|
# Split the path into pieces in between forward slashes.
|
1430
1559
|
#
|
1431
1560
|
segments = path.split('/').map! do |segment|
|
1432
1561
|
ignore = []
|
1433
|
-
|
1562
|
+
|
1434
1563
|
# Special character handling.
|
1435
1564
|
#
|
1436
1565
|
pattern = segment.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c|
|
@@ -1440,9 +1569,9 @@ module Sinatra
|
|
1440
1569
|
match.split(//).map {|char| char =~ /[A-Z]/ ? "[#{char}#{char.tr('A-Z', 'a-z')}]" : char}.join
|
1441
1570
|
end
|
1442
1571
|
end
|
1443
|
-
|
1572
|
+
|
1444
1573
|
ignore = ignore.uniq.join
|
1445
|
-
|
1574
|
+
|
1446
1575
|
# Key handling.
|
1447
1576
|
#
|
1448
1577
|
pattern.gsub(/((:\w+)|\*)/) do |match|
|
@@ -1452,12 +1581,12 @@ module Sinatra
|
|
1452
1581
|
else
|
1453
1582
|
keys << $2[1..-1]
|
1454
1583
|
ignore_pattern = safe_ignore(ignore)
|
1455
|
-
|
1584
|
+
|
1456
1585
|
ignore_pattern
|
1457
1586
|
end
|
1458
1587
|
end
|
1459
1588
|
end
|
1460
|
-
|
1589
|
+
|
1461
1590
|
# Special case handling.
|
1462
1591
|
#
|
1463
1592
|
if segment = segments.pop
|
@@ -1481,8 +1610,6 @@ module Sinatra
|
|
1481
1610
|
end
|
1482
1611
|
end
|
1483
1612
|
|
1484
|
-
URI = ::URI.const_defined?(:Parser) ? ::URI::Parser.new : ::URI
|
1485
|
-
|
1486
1613
|
def encoded(char)
|
1487
1614
|
enc = URI.escape(char)
|
1488
1615
|
enc = "(?:#{escaped(char, enc).join('|')})" if enc == char
|
@@ -1517,100 +1644,6 @@ module Sinatra
|
|
1517
1644
|
end
|
1518
1645
|
end
|
1519
1646
|
|
1520
|
-
public
|
1521
|
-
# Makes the methods defined in the block and in the Modules given
|
1522
|
-
# in `extensions` available to the handlers and templates
|
1523
|
-
def helpers(*extensions, &block)
|
1524
|
-
class_eval(&block) if block_given?
|
1525
|
-
include(*extensions) if extensions.any?
|
1526
|
-
end
|
1527
|
-
|
1528
|
-
# Register an extension. Alternatively take a block from which an
|
1529
|
-
# extension will be created and registered on the fly.
|
1530
|
-
def register(*extensions, &block)
|
1531
|
-
extensions << Module.new(&block) if block_given?
|
1532
|
-
@extensions += extensions
|
1533
|
-
extensions.each do |extension|
|
1534
|
-
extend extension
|
1535
|
-
extension.registered(self) if extension.respond_to?(:registered)
|
1536
|
-
end
|
1537
|
-
end
|
1538
|
-
|
1539
|
-
def development?; environment == :development end
|
1540
|
-
def production?; environment == :production end
|
1541
|
-
def test?; environment == :test end
|
1542
|
-
|
1543
|
-
# Set configuration options for Sinatra and/or the app.
|
1544
|
-
# Allows scoping of settings for certain environments.
|
1545
|
-
def configure(*envs, &block)
|
1546
|
-
yield self if envs.empty? || envs.include?(environment.to_sym)
|
1547
|
-
end
|
1548
|
-
|
1549
|
-
# Use the specified Rack middleware
|
1550
|
-
def use(middleware, *args, &block)
|
1551
|
-
@prototype = nil
|
1552
|
-
@middleware << [middleware, args, block]
|
1553
|
-
end
|
1554
|
-
|
1555
|
-
def quit!(server, handler_name)
|
1556
|
-
# Use Thin's hard #stop! if available, otherwise just #stop.
|
1557
|
-
server.respond_to?(:stop!) ? server.stop! : server.stop
|
1558
|
-
$stderr.puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
|
1559
|
-
end
|
1560
|
-
|
1561
|
-
# Run the Sinatra app as a self-hosted server using
|
1562
|
-
# Thin, Puma, Mongrel, or WEBrick (in that order). If given a block, will call
|
1563
|
-
# with the constructed handler once we have taken the stage.
|
1564
|
-
def run!(options = {})
|
1565
|
-
set options
|
1566
|
-
handler = detect_rack_handler
|
1567
|
-
handler_name = handler.name.gsub(/.*::/, '')
|
1568
|
-
server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
|
1569
|
-
handler.run self, server_settings.merge(:Port => port, :Host => bind) do |server|
|
1570
|
-
unless handler_name =~ /cgi/i
|
1571
|
-
$stderr.puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
|
1572
|
-
"on #{port} for #{environment} with backup from #{handler_name}"
|
1573
|
-
end
|
1574
|
-
[:INT, :TERM].each { |sig| trap(sig) { quit!(server, handler_name) } }
|
1575
|
-
server.threaded = settings.threaded if server.respond_to? :threaded=
|
1576
|
-
set :running, true
|
1577
|
-
yield server if block_given?
|
1578
|
-
end
|
1579
|
-
rescue Errno::EADDRINUSE
|
1580
|
-
$stderr.puts "== Someone is already performing on port #{port}!"
|
1581
|
-
end
|
1582
|
-
|
1583
|
-
# The prototype instance used to process requests.
|
1584
|
-
def prototype
|
1585
|
-
@prototype ||= new
|
1586
|
-
end
|
1587
|
-
|
1588
|
-
# Create a new instance without middleware in front of it.
|
1589
|
-
alias new! new unless method_defined? :new!
|
1590
|
-
|
1591
|
-
# Create a new instance of the class fronted by its middleware
|
1592
|
-
# pipeline. The object is guaranteed to respond to #call but may not be
|
1593
|
-
# an instance of the class new was called on.
|
1594
|
-
def new(*args, &bk)
|
1595
|
-
instance = new!(*args, &bk)
|
1596
|
-
Wrapper.new(build(instance).to_app, instance)
|
1597
|
-
end
|
1598
|
-
|
1599
|
-
# Creates a Rack::Builder instance with all the middleware set up and
|
1600
|
-
# the given +app+ as end point.
|
1601
|
-
def build(app)
|
1602
|
-
builder = Rack::Builder.new
|
1603
|
-
setup_default_middleware builder
|
1604
|
-
setup_middleware builder
|
1605
|
-
builder.run app
|
1606
|
-
builder
|
1607
|
-
end
|
1608
|
-
|
1609
|
-
def call(env)
|
1610
|
-
synchronize { prototype.call(env) }
|
1611
|
-
end
|
1612
|
-
|
1613
|
-
private
|
1614
1647
|
def setup_default_middleware(builder)
|
1615
1648
|
builder.use ExtendedRack
|
1616
1649
|
builder.use ShowExceptions if show_exceptions?
|
@@ -1694,37 +1727,6 @@ module Sinatra
|
|
1694
1727
|
end
|
1695
1728
|
end
|
1696
1729
|
|
1697
|
-
public
|
1698
|
-
CALLERS_TO_IGNORE = [ # :nodoc:
|
1699
|
-
/\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
|
1700
|
-
/lib\/tilt.*\.rb$/, # all tilt code
|
1701
|
-
/^\(.*\)$/, # generated code
|
1702
|
-
/rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks
|
1703
|
-
/active_support/, # active_support require hacks
|
1704
|
-
/bundler(\/runtime)?\.rb/, # bundler require hacks
|
1705
|
-
/<internal:/, # internal in ruby >= 1.9.2
|
1706
|
-
/src\/kernel\/bootstrap\/[A-Z]/ # maglev kernel files
|
1707
|
-
]
|
1708
|
-
|
1709
|
-
# contrary to what the comment said previously, rubinius never supported this
|
1710
|
-
if defined?(RUBY_IGNORE_CALLERS)
|
1711
|
-
warn "RUBY_IGNORE_CALLERS is deprecated and will no longer be supported by Sinatra 2.0"
|
1712
|
-
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS)
|
1713
|
-
end
|
1714
|
-
|
1715
|
-
# Like Kernel#caller but excluding certain magic entries and without
|
1716
|
-
# line / method information; the resulting array contains filenames only.
|
1717
|
-
def caller_files
|
1718
|
-
cleaned_caller(1).flatten
|
1719
|
-
end
|
1720
|
-
|
1721
|
-
# Like caller_files, but containing Arrays rather than strings with the
|
1722
|
-
# first element being the file, and the second being the line.
|
1723
|
-
def caller_locations
|
1724
|
-
cleaned_caller 2
|
1725
|
-
end
|
1726
|
-
|
1727
|
-
private
|
1728
1730
|
# used for deprecation warnings
|
1729
1731
|
def warn(message)
|
1730
1732
|
super message + "\n\tfrom #{cleaned_caller.first.join(':')}"
|
@@ -1795,7 +1797,7 @@ module Sinatra
|
|
1795
1797
|
set :running, false # is the built-in server running now?
|
1796
1798
|
set :server, %w[HTTP webrick]
|
1797
1799
|
set :bind, Proc.new { development? ? 'localhost' : '0.0.0.0' }
|
1798
|
-
set :port, Integer(ENV['PORT']
|
1800
|
+
set :port, Integer(ENV['PORT'] && !ENV['PORT'].empty? ? ENV['PORT'] : 4567)
|
1799
1801
|
|
1800
1802
|
ruby_engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
|
1801
1803
|
|