sinatra 2.0.5 → 2.1.0
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 +4 -4
- data/CHANGELOG.md +74 -0
- data/CONTRIBUTING.md +1 -7
- data/Gemfile +8 -2
- data/README.de.md +4 -4
- data/README.es.md +3 -3
- data/README.fr.md +183 -86
- data/README.hu.md +3 -3
- data/README.ja.md +2 -2
- data/README.ko.md +2 -2
- data/README.md +69 -34
- data/README.pt-br.md +2357 -330
- data/README.pt-pt.md +3 -3
- data/README.ru.md +4 -4
- data/README.zh.md +2 -2
- data/Rakefile +8 -5
- data/VERSION +1 -1
- data/examples/chat.rb +2 -1
- data/examples/rainbows.conf +3 -0
- data/examples/rainbows.rb +20 -0
- data/examples/stream.ru +4 -4
- data/lib/sinatra/base.rb +107 -73
- data/lib/sinatra/indifferent_hash.rb +13 -9
- data/lib/sinatra/main.rb +30 -11
- data/lib/sinatra/show_exceptions.rb +2 -37
- data/lib/sinatra/version.rb +1 -1
- data/sinatra.gemspec +2 -2
- metadata +10 -9
data/README.pt-pt.md
CHANGED
@@ -121,7 +121,7 @@ Arquivos estáticos são disponibilizados a partir do directório
|
|
121
121
|
`:public_folder`
|
122
122
|
|
123
123
|
```ruby
|
124
|
-
set :public_folder,
|
124
|
+
set :public_folder, __dir__ + '/estatico'
|
125
125
|
```
|
126
126
|
|
127
127
|
Note que o nome do directório público não é incluido no URL. Um arquivo
|
@@ -134,7 +134,7 @@ Templates presumem-se estar localizados sob o directório `./views`. Para
|
|
134
134
|
utilizar um directório de views diferente:
|
135
135
|
|
136
136
|
```ruby
|
137
|
-
set :views,
|
137
|
+
set :views, __dir__ + '/modelo'
|
138
138
|
```
|
139
139
|
|
140
140
|
Uma coisa importante a ser lembrada é que você sempre tem as referências
|
@@ -757,7 +757,7 @@ Alternativamente, pode adicionar o directório do `sinatra/lib` no
|
|
757
757
|
`LOAD_PATH` do seu aplicativo:
|
758
758
|
|
759
759
|
```ruby
|
760
|
-
$LOAD_PATH.unshift
|
760
|
+
$LOAD_PATH.unshift __dir__ + '/sinatra/lib'
|
761
761
|
require 'rubygems'
|
762
762
|
require 'sinatra'
|
763
763
|
|
data/README.ru.md
CHANGED
@@ -431,7 +431,7 @@ end
|
|
431
431
|
месторасположение при помощи опции `:public_folder`:
|
432
432
|
|
433
433
|
```ruby
|
434
|
-
set :public_folder,
|
434
|
+
set :public_folder, __dir__ + '/static'
|
435
435
|
```
|
436
436
|
|
437
437
|
Учтите, что имя директории со статическими файлами не включено в URL.
|
@@ -2226,7 +2226,7 @@ end
|
|
2226
2226
|
### Настройка защиты от атак
|
2227
2227
|
|
2228
2228
|
Sinatra использует
|
2229
|
-
[Rack::Protection](https://github.com/sinatra/rack-protection#readme) для защиты
|
2229
|
+
[Rack::Protection](https://github.com/sinatra/sinatra/tree/master/rack-protection#readme) для защиты
|
2230
2230
|
приложения от простых атак. Вы можете легко выключить эту защиту (что сделает
|
2231
2231
|
ваше приложение чрезвычайно уязвимым к большому числу различных уязвимостей):
|
2232
2232
|
|
@@ -3089,9 +3089,9 @@ thin --threaded start
|
|
3089
3089
|
|
3090
3090
|
Следующие версии Ruby официально поддерживаются:
|
3091
3091
|
<dl>
|
3092
|
-
<dt>Ruby 2.
|
3092
|
+
<dt>Ruby 2.3</dt>
|
3093
3093
|
<dd>
|
3094
|
-
Версия 2.
|
3094
|
+
Версия 2.3 полностью поддерживается и рекомендуется. В настоящее время нет
|
3095
3095
|
планов отказаться от официальной поддержки.
|
3096
3096
|
</dd>
|
3097
3097
|
|
data/README.zh.md
CHANGED
@@ -393,7 +393,7 @@ end
|
|
393
393
|
静态文件从 `./public` 目录提供服务。可以通过设置`:public_folder` 选项设定一个不同的位置:
|
394
394
|
|
395
395
|
```ruby
|
396
|
-
set :public_folder,
|
396
|
+
set :public_folder, __dir__ + '/static'
|
397
397
|
```
|
398
398
|
|
399
399
|
请注意 public 目录名并没有包含在 URL 中。文件 `./public/css/style.css` 可以通过
|
@@ -2027,7 +2027,7 @@ end
|
|
2027
2027
|
|
2028
2028
|
### 配置攻击防护
|
2029
2029
|
|
2030
|
-
Sinatra 使用 [Rack::Protection](https://github.com/sinatra/rack-protection#readme)
|
2030
|
+
Sinatra 使用 [Rack::Protection](https://github.com/sinatra/sinatra/tree/master/rack-protection#readme)
|
2031
2031
|
来抵御常见的攻击。你可以轻易地禁用该行为(但这会大大增加应用被攻击的概率)。
|
2032
2032
|
|
2033
2033
|
```ruby
|
data/Rakefile
CHANGED
@@ -202,11 +202,14 @@ if defined?(Gem)
|
|
202
202
|
|
203
203
|
desc "Commits the version to github repository"
|
204
204
|
task :commit_version do
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
205
|
+
%w[
|
206
|
+
lib/sinatra
|
207
|
+
sinatra-contrib/lib/sinatra/contrib
|
208
|
+
rack-protection/lib/rack/protection
|
209
|
+
].each do |path|
|
210
|
+
path = File.join(path, 'version.rb')
|
211
|
+
File.write(path, File.read(path).sub(/VERSION = '(.+?)'/, "VERSION = '#{source_version}'"))
|
212
|
+
end
|
210
213
|
|
211
214
|
sh <<-SH
|
212
215
|
git commit --allow-empty -a -m '#{source_version} release' &&
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0
|
1
|
+
2.1.0
|
data/examples/chat.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rainbows'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Handler
|
5
|
+
class Rainbows
|
6
|
+
def self.run(app, **options)
|
7
|
+
rainbows_options = {
|
8
|
+
listeners: ["#{options[:Host]}:#{options[:Port]}"],
|
9
|
+
worker_processes: 1,
|
10
|
+
timeout: 30,
|
11
|
+
config_file: ::File.expand_path('rainbows.conf', __dir__),
|
12
|
+
}
|
13
|
+
|
14
|
+
::Rainbows::HttpServer.new(app, rainbows_options).start.join
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
register :rainbows, ::Rack::Handler::Rainbows
|
19
|
+
end
|
20
|
+
end
|
data/examples/stream.ru
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
#
|
3
3
|
# run *one* of these:
|
4
4
|
#
|
5
|
-
# rackup -s mongrel stream.ru
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
5
|
+
# rackup -s mongrel stream.ru # gem install mongrel
|
6
|
+
# unicorn stream.ru # gem install unicorn
|
7
|
+
# puma stream.ru # gem install puma
|
8
|
+
# rainbows -c rainbows.conf stream.ru # gem install rainbows eventmachine
|
9
9
|
|
10
10
|
require 'sinatra/base'
|
11
11
|
|
data/lib/sinatra/base.rb
CHANGED
@@ -43,12 +43,11 @@ module Sinatra
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def preferred_type(*types)
|
46
|
-
|
47
|
-
return accepts.first if types.empty?
|
46
|
+
return accept.first if types.empty?
|
48
47
|
types.flatten!
|
49
|
-
return types.first if
|
50
|
-
|
51
|
-
type = types.detect { |t|
|
48
|
+
return types.first if accept.empty?
|
49
|
+
accept.detect do |accept_header|
|
50
|
+
type = types.detect { |t| MimeTypeEntry.new(t).accepts?(accept_header) }
|
52
51
|
return type if type
|
53
52
|
end
|
54
53
|
end
|
@@ -81,8 +80,6 @@ module Sinatra
|
|
81
80
|
raise BadRequest, "Invalid query parameters: #{Rack::Utils.escape_html(e.message)}"
|
82
81
|
end
|
83
82
|
|
84
|
-
private
|
85
|
-
|
86
83
|
class AcceptEntry
|
87
84
|
attr_accessor :params
|
88
85
|
attr_reader :entry
|
@@ -125,6 +122,35 @@ module Sinatra
|
|
125
122
|
to_str.send(*args, &block)
|
126
123
|
end
|
127
124
|
end
|
125
|
+
|
126
|
+
class MimeTypeEntry
|
127
|
+
attr_reader :params
|
128
|
+
|
129
|
+
def initialize(entry)
|
130
|
+
params = entry.scan(HEADER_PARAM).map! do |s|
|
131
|
+
key, value = s.strip.split('=', 2)
|
132
|
+
value = value[1..-2].gsub(/\\(.)/, '\1') if value.start_with?('"')
|
133
|
+
[key, value]
|
134
|
+
end
|
135
|
+
|
136
|
+
@type = entry[/[^;]+/].delete(' ')
|
137
|
+
@params = Hash[params]
|
138
|
+
end
|
139
|
+
|
140
|
+
def accepts?(entry)
|
141
|
+
File.fnmatch(entry, self) && matches_params?(entry.params)
|
142
|
+
end
|
143
|
+
|
144
|
+
def to_str
|
145
|
+
@type
|
146
|
+
end
|
147
|
+
|
148
|
+
def matches_params?(params)
|
149
|
+
return true if @params.empty?
|
150
|
+
|
151
|
+
params.all? { |k,v| !@params.has_key?(k) || @params[k] == v }
|
152
|
+
end
|
153
|
+
end
|
128
154
|
end
|
129
155
|
|
130
156
|
# The response object. See Rack::Response and Rack::Response::Helpers for
|
@@ -133,10 +159,6 @@ module Sinatra
|
|
133
159
|
# http://rubydoc.info/github/rack/rack/master/Rack/Response/Helpers
|
134
160
|
class Response < Rack::Response
|
135
161
|
DROP_BODY_RESPONSES = [204, 304]
|
136
|
-
def initialize(*)
|
137
|
-
super
|
138
|
-
headers['Content-Type'] ||= 'text/html'
|
139
|
-
end
|
140
162
|
|
141
163
|
def body=(value)
|
142
164
|
value = value.body while Rack::Response === value
|
@@ -163,7 +185,7 @@ module Sinatra
|
|
163
185
|
if calculate_content_length?
|
164
186
|
# if some other code has already set Content-Length, don't muck with it
|
165
187
|
# currently, this would be the static file-handler
|
166
|
-
headers["Content-Length"] = body.
|
188
|
+
headers["Content-Length"] = body.map(&:bytesize).reduce(0, :+).to_s
|
167
189
|
end
|
168
190
|
|
169
191
|
[status.to_i, headers, result]
|
@@ -184,7 +206,7 @@ module Sinatra
|
|
184
206
|
end
|
185
207
|
end
|
186
208
|
|
187
|
-
# Some Rack handlers (
|
209
|
+
# Some Rack handlers (Rainbows!) implement an extended body object protocol, however,
|
188
210
|
# some middleware (namely Rack::Lint) will break it by not mirroring the methods in question.
|
189
211
|
# This middleware will detect an extended body object and will make sure it reaches the
|
190
212
|
# handler directly. We do this here, so our middleware and middleware set up by the app will
|
@@ -451,7 +473,7 @@ module Sinatra
|
|
451
473
|
#
|
452
474
|
# The close parameter specifies whether Stream#close should be called
|
453
475
|
# after the block has been executed. This is only relevant for evented
|
454
|
-
# servers like
|
476
|
+
# servers like Rainbows.
|
455
477
|
def stream(keep_open = false)
|
456
478
|
scheduler = env['async.callback'] ? EventMachine : Stream
|
457
479
|
current = @params.dup
|
@@ -647,8 +669,6 @@ module Sinatra
|
|
647
669
|
end
|
648
670
|
end
|
649
671
|
|
650
|
-
private
|
651
|
-
|
652
672
|
# Template rendering methods. Each method takes the name of a template
|
653
673
|
# to render as a Symbol and returns a String with the rendered output,
|
654
674
|
# as well as an optional hash with additional options.
|
@@ -722,6 +742,7 @@ module Sinatra
|
|
722
742
|
end
|
723
743
|
|
724
744
|
def markdown(template, options = {}, locals = {})
|
745
|
+
options[:exclude_outvar] = true
|
725
746
|
render :markdown, template, options, locals
|
726
747
|
end
|
727
748
|
|
@@ -786,15 +807,8 @@ module Sinatra
|
|
786
807
|
def find_template(views, name, engine)
|
787
808
|
yield ::File.join(views, "#{name}.#{@preferred_extension}")
|
788
809
|
|
789
|
-
|
790
|
-
|
791
|
-
next unless ext != @preferred_extension and engines.include? engine
|
792
|
-
yield ::File.join(views, "#{name}.#{ext}")
|
793
|
-
end
|
794
|
-
else
|
795
|
-
Tilt.default_mapping.extensions_for(engine).each do |ext|
|
796
|
-
yield ::File.join(views, "#{name}.#{ext}") unless ext == @preferred_extension
|
797
|
-
end
|
810
|
+
Tilt.default_mapping.extensions_for(engine).each do |ext|
|
811
|
+
yield ::File.join(views, "#{name}.#{ext}") unless ext == @preferred_extension
|
798
812
|
end
|
799
813
|
end
|
800
814
|
|
@@ -825,10 +839,11 @@ module Sinatra
|
|
825
839
|
content_type = options.delete(:content_type) || content_type
|
826
840
|
layout_engine = options.delete(:layout_engine) || engine
|
827
841
|
scope = options.delete(:scope) || self
|
842
|
+
exclude_outvar = options.delete(:exclude_outvar)
|
828
843
|
options.delete(:layout)
|
829
844
|
|
830
845
|
# set some defaults
|
831
|
-
options[:outvar]
|
846
|
+
options[:outvar] ||= '@_out_buf' unless exclude_outvar
|
832
847
|
options[:default_encoding] ||= settings.default_encoding
|
833
848
|
|
834
849
|
# compile and render template
|
@@ -905,6 +920,7 @@ module Sinatra
|
|
905
920
|
super()
|
906
921
|
@app = app
|
907
922
|
@template_cache = Tilt::Cache.new
|
923
|
+
@pinned_response = nil # whether a before! filter pinned the content-type
|
908
924
|
yield self if block_given?
|
909
925
|
end
|
910
926
|
|
@@ -920,15 +936,14 @@ module Sinatra
|
|
920
936
|
@response = Response.new
|
921
937
|
template_cache.clear if settings.reload_templates
|
922
938
|
|
923
|
-
@response['Content-Type'] = nil
|
924
939
|
invoke { dispatch! }
|
925
940
|
invoke { error_block!(response.status) } unless @env['sinatra.error']
|
926
941
|
|
927
942
|
unless @response['Content-Type']
|
928
|
-
if Array === body
|
943
|
+
if Array === body && body[0].respond_to?(:content_type)
|
929
944
|
content_type body[0].content_type
|
930
|
-
|
931
|
-
content_type
|
945
|
+
elsif default = settings.default_content_type
|
946
|
+
content_type default
|
932
947
|
end
|
933
948
|
end
|
934
949
|
|
@@ -978,15 +993,21 @@ module Sinatra
|
|
978
993
|
private
|
979
994
|
|
980
995
|
# Run filters defined on the class and all superclasses.
|
996
|
+
# Accepts an optional block to call after each filter is applied.
|
981
997
|
def filter!(type, base = settings)
|
982
998
|
filter! type, base.superclass if base.superclass.respond_to?(:filters)
|
983
|
-
base.filters[type].each
|
999
|
+
base.filters[type].each do |args|
|
1000
|
+
result = process_route(*args)
|
1001
|
+
yield result if block_given?
|
1002
|
+
end
|
984
1003
|
end
|
985
1004
|
|
986
1005
|
# Run routes defined on the class and all superclasses.
|
987
1006
|
def route!(base = settings, pass_block = nil)
|
988
1007
|
if routes = base.routes[@request.request_method]
|
989
1008
|
routes.each do |pattern, conditions, block|
|
1009
|
+
@response.delete_header('Content-Type') unless @pinned_response
|
1010
|
+
|
990
1011
|
returned_pass_block = process_route(pattern, conditions) do |*args|
|
991
1012
|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
|
992
1013
|
route_eval { block[*args] }
|
@@ -1024,7 +1045,7 @@ module Sinatra
|
|
1024
1045
|
|
1025
1046
|
params.delete("ignore") # TODO: better params handling, maybe turn it into "smart" object or detect changes
|
1026
1047
|
force_encoding(params)
|
1027
|
-
|
1048
|
+
@params = @params.merge(params) if params.any?
|
1028
1049
|
|
1029
1050
|
regexp_exists = pattern.is_a?(Mustermann::Regular) || (pattern.respond_to?(:patterns) && pattern.patterns.any? {|subpattern| subpattern.is_a?(Mustermann::Regular)} )
|
1030
1051
|
if regexp_exists
|
@@ -1043,7 +1064,8 @@ module Sinatra
|
|
1043
1064
|
@env['sinatra.error.params'] = @params
|
1044
1065
|
raise
|
1045
1066
|
ensure
|
1046
|
-
|
1067
|
+
params ||= {}
|
1068
|
+
params.each { |k, _| @params.delete(k) } unless @env['sinatra.error.params']
|
1047
1069
|
end
|
1048
1070
|
|
1049
1071
|
# No matching route was found or all routes passed. The default
|
@@ -1055,7 +1077,7 @@ module Sinatra
|
|
1055
1077
|
if @app
|
1056
1078
|
forward
|
1057
1079
|
else
|
1058
|
-
raise NotFound
|
1080
|
+
raise NotFound, "#{request.request_method} #{request.path_info}"
|
1059
1081
|
end
|
1060
1082
|
end
|
1061
1083
|
|
@@ -1063,7 +1085,10 @@ module Sinatra
|
|
1063
1085
|
# a matching file is found, returns nil otherwise.
|
1064
1086
|
def static!(options = {})
|
1065
1087
|
return if (public_dir = settings.public_folder).nil?
|
1066
|
-
path =
|
1088
|
+
path = "#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}"
|
1089
|
+
return unless valid_path?(path)
|
1090
|
+
|
1091
|
+
path = File.expand_path(path)
|
1067
1092
|
return unless File.file?(path)
|
1068
1093
|
|
1069
1094
|
env['sinatra.static_file'] = path
|
@@ -1089,11 +1114,18 @@ module Sinatra
|
|
1089
1114
|
|
1090
1115
|
# Dispatch a request with error handling.
|
1091
1116
|
def dispatch!
|
1092
|
-
|
1117
|
+
# Avoid passing frozen string in force_encoding
|
1118
|
+
@params.merge!(@request.params).each do |key, val|
|
1119
|
+
next unless val.respond_to?(:force_encoding)
|
1120
|
+
val = val.dup if val.frozen?
|
1121
|
+
@params[key] = force_encoding(val)
|
1122
|
+
end
|
1093
1123
|
|
1094
1124
|
invoke do
|
1095
1125
|
static! if settings.static? && (request.get? || request.head?)
|
1096
|
-
filter! :before
|
1126
|
+
filter! :before do
|
1127
|
+
@pinned_response = !@response['Content-Type'].nil?
|
1128
|
+
end
|
1097
1129
|
route!
|
1098
1130
|
end
|
1099
1131
|
rescue ::Exception => boom
|
@@ -1123,19 +1155,27 @@ module Sinatra
|
|
1123
1155
|
|
1124
1156
|
status(500) unless status.between? 400, 599
|
1125
1157
|
|
1126
|
-
boom_message = boom.message if boom.message && boom.message != boom.class.name
|
1127
1158
|
if server_error?
|
1128
1159
|
dump_errors! boom if settings.dump_errors?
|
1129
1160
|
raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler
|
1130
1161
|
elsif not_found?
|
1131
1162
|
headers['X-Cascade'] = 'pass' if settings.x_cascade?
|
1132
|
-
body boom_message || '<h1>Not Found</h1>'
|
1133
|
-
elsif bad_request?
|
1134
|
-
body boom_message || '<h1>Bad Request</h1>'
|
1135
1163
|
end
|
1136
1164
|
|
1137
|
-
res = error_block!(boom.class, boom) || error_block!(status, boom)
|
1138
|
-
|
1165
|
+
if res = error_block!(boom.class, boom) || error_block!(status, boom)
|
1166
|
+
return res
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
if not_found? || bad_request?
|
1170
|
+
if boom.message && boom.message != boom.class.name
|
1171
|
+
body boom.message
|
1172
|
+
else
|
1173
|
+
content_type 'text/html'
|
1174
|
+
body '<h1>' + (not_found? ? 'Not Found' : 'Bad Request') + '</h1>'
|
1175
|
+
end
|
1176
|
+
end
|
1177
|
+
|
1178
|
+
return unless server_error?
|
1139
1179
|
raise boom if settings.raise_errors? or settings.show_exceptions?
|
1140
1180
|
error_block! Exception, boom
|
1141
1181
|
end
|
@@ -1168,7 +1208,7 @@ module Sinatra
|
|
1168
1208
|
/^\(.*\)$/, # generated code
|
1169
1209
|
/rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks
|
1170
1210
|
/active_support/, # active_support require hacks
|
1171
|
-
/bundler(\/runtime)?\.rb/,
|
1211
|
+
/bundler(\/(?:runtime|inline))?\.rb/, # bundler require hacks
|
1172
1212
|
/<internal:/, # internal in ruby >= 1.9.2
|
1173
1213
|
/src\/kernel\/bootstrap\/[A-Z]/ # maglev kernel files
|
1174
1214
|
]
|
@@ -1345,19 +1385,19 @@ module Sinatra
|
|
1345
1385
|
# context as route handlers and may access/modify the request and
|
1346
1386
|
# response.
|
1347
1387
|
def before(path = /.*/, **options, &block)
|
1348
|
-
add_filter(:before, path, options, &block)
|
1388
|
+
add_filter(:before, path, **options, &block)
|
1349
1389
|
end
|
1350
1390
|
|
1351
1391
|
# Define an after filter; runs after all requests within the same
|
1352
1392
|
# context as route handlers and may access/modify the request and
|
1353
1393
|
# response.
|
1354
1394
|
def after(path = /.*/, **options, &block)
|
1355
|
-
add_filter(:after, path, options, &block)
|
1395
|
+
add_filter(:after, path, **options, &block)
|
1356
1396
|
end
|
1357
1397
|
|
1358
1398
|
# add a filter
|
1359
1399
|
def add_filter(type, path = /.*/, **options, &block)
|
1360
|
-
filters[type] << compile!(type, path, block, options)
|
1400
|
+
filters[type] << compile!(type, path, block, **options)
|
1361
1401
|
end
|
1362
1402
|
|
1363
1403
|
# Add a route condition. The route is considered non-matching when the
|
@@ -1402,7 +1442,7 @@ module Sinatra
|
|
1402
1442
|
# in `extensions` available to the handlers and templates
|
1403
1443
|
def helpers(*extensions, &block)
|
1404
1444
|
class_eval(&block) if block_given?
|
1405
|
-
|
1445
|
+
prepend(*extensions) if extensions.any?
|
1406
1446
|
end
|
1407
1447
|
|
1408
1448
|
# Register an extension. Alternatively take a block from which an
|
@@ -1445,7 +1485,7 @@ module Sinatra
|
|
1445
1485
|
alias_method :stop!, :quit!
|
1446
1486
|
|
1447
1487
|
# Run the Sinatra app as a self-hosted server using
|
1448
|
-
#
|
1488
|
+
# Puma, Mongrel, or WEBrick (in that order). If given a block, will call
|
1449
1489
|
# with the constructed handler once we have taken the stage.
|
1450
1490
|
def run!(options = {}, &block)
|
1451
1491
|
return if running?
|
@@ -1522,7 +1562,7 @@ module Sinatra
|
|
1522
1562
|
# behavior, by ensuring an instance exists:
|
1523
1563
|
prototype
|
1524
1564
|
# Run the instance we created:
|
1525
|
-
handler.run(self, server_settings) do |server|
|
1565
|
+
handler.run(self, **server_settings) do |server|
|
1526
1566
|
unless suppress_messages?
|
1527
1567
|
$stderr.puts "== Sinatra (v#{Sinatra::VERSION}) has taken the stage on #{port} for #{environment} with backup from #{handler_name}"
|
1528
1568
|
end
|
@@ -1601,7 +1641,7 @@ module Sinatra
|
|
1601
1641
|
|
1602
1642
|
def route(verb, path, options = {}, &block)
|
1603
1643
|
enable :empty_path_info if path == "" and empty_path_info.nil?
|
1604
|
-
signature = compile!(verb, path, block, options)
|
1644
|
+
signature = compile!(verb, path, block, **options)
|
1605
1645
|
(@routes[verb] ||= []) << signature
|
1606
1646
|
invoke_hook(:route_added, verb, path, block)
|
1607
1647
|
signature
|
@@ -1638,7 +1678,7 @@ module Sinatra
|
|
1638
1678
|
end
|
1639
1679
|
|
1640
1680
|
def compile(path, route_mustermann_opts = {})
|
1641
|
-
Mustermann.new(path, mustermann_opts.merge(route_mustermann_opts))
|
1681
|
+
Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts))
|
1642
1682
|
end
|
1643
1683
|
|
1644
1684
|
def setup_default_middleware(builder)
|
@@ -1743,29 +1783,22 @@ module Sinatra
|
|
1743
1783
|
end
|
1744
1784
|
end
|
1745
1785
|
|
1746
|
-
#
|
1747
|
-
#
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
if data.respond_to? :force_encoding
|
1757
|
-
data.force_encoding(encoding).encode!
|
1758
|
-
elsif data.respond_to? :each_value
|
1759
|
-
data.each_value { |v| force_encoding(v, encoding) }
|
1760
|
-
elsif data.respond_to? :each
|
1761
|
-
data.each { |v| force_encoding(v, encoding) }
|
1762
|
-
end
|
1763
|
-
data
|
1786
|
+
# Force data to specified encoding. It defaults to settings.default_encoding
|
1787
|
+
# which is UTF-8 by default
|
1788
|
+
def self.force_encoding(data, encoding = default_encoding)
|
1789
|
+
return if data == settings || data.is_a?(Tempfile)
|
1790
|
+
if data.respond_to? :force_encoding
|
1791
|
+
data.force_encoding(encoding).encode!
|
1792
|
+
elsif data.respond_to? :each_value
|
1793
|
+
data.each_value { |v| force_encoding(v, encoding) }
|
1794
|
+
elsif data.respond_to? :each
|
1795
|
+
data.each { |v| force_encoding(v, encoding) }
|
1764
1796
|
end
|
1765
|
-
|
1766
|
-
def self.force_encoding(data, *) data end
|
1797
|
+
data
|
1767
1798
|
end
|
1768
1799
|
|
1800
|
+
def force_encoding(*args) settings.force_encoding(*args) end
|
1801
|
+
|
1769
1802
|
reset!
|
1770
1803
|
|
1771
1804
|
set :environment, (ENV['APP_ENV'] || ENV['RACK_ENV'] || :development).to_sym
|
@@ -1783,6 +1816,7 @@ module Sinatra
|
|
1783
1816
|
set :add_charset, %w[javascript xml xhtml+xml].map { |t| "application/#{t}" }
|
1784
1817
|
settings.add_charset << /^text\//
|
1785
1818
|
set :mustermann_opts, {}
|
1819
|
+
set :default_content_type, 'text/html'
|
1786
1820
|
|
1787
1821
|
# explicitly generating a session secret eagerly to play nice with preforking
|
1788
1822
|
begin
|
@@ -1843,7 +1877,7 @@ module Sinatra
|
|
1843
1877
|
|
1844
1878
|
configure :development do
|
1845
1879
|
get '/__sinatra__/:image.png' do
|
1846
|
-
filename =
|
1880
|
+
filename = __dir__ + "/images/#{params[:image].to_i}.png"
|
1847
1881
|
content_type :png
|
1848
1882
|
send_file filename
|
1849
1883
|
end
|