sinatra-rack-3-commonlit 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/AUTHORS.md +81 -0
- data/CHANGELOG.md +1742 -0
- data/CONTRIBUTING.md +100 -0
- data/Gemfile +68 -0
- data/LICENSE +26 -0
- data/MAINTENANCE.md +29 -0
- data/README.md +3016 -0
- data/Rakefile +216 -0
- data/SECURITY.md +35 -0
- data/VERSION +1 -0
- data/examples/chat.rb +75 -0
- data/examples/lifecycle_events.rb +20 -0
- data/examples/rainbows.conf +3 -0
- data/examples/rainbows.rb +22 -0
- data/examples/simple.rb +5 -0
- data/examples/stream.ru +27 -0
- data/lib/sinatra/base.rb +2111 -0
- data/lib/sinatra/images/404.png +0 -0
- data/lib/sinatra/images/500.png +0 -0
- data/lib/sinatra/indifferent_hash.rb +206 -0
- data/lib/sinatra/main.rb +56 -0
- data/lib/sinatra/show_exceptions.rb +364 -0
- data/lib/sinatra/version.rb +5 -0
- data/lib/sinatra.rb +5 -0
- data/sinatra.gemspec +56 -0
- metadata +202 -0
Binary file
|
Binary file
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
# A poor man's ActiveSupport::HashWithIndifferentAccess, with all the Rails-y
|
5
|
+
# stuff removed.
|
6
|
+
#
|
7
|
+
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are
|
8
|
+
# considered to be the same.
|
9
|
+
#
|
10
|
+
# rgb = Sinatra::IndifferentHash.new
|
11
|
+
#
|
12
|
+
# rgb[:black] = '#000000' # symbol assignment
|
13
|
+
# rgb[:black] # => '#000000' # symbol retrieval
|
14
|
+
# rgb['black'] # => '#000000' # string retrieval
|
15
|
+
#
|
16
|
+
# rgb['white'] = '#FFFFFF' # string assignment
|
17
|
+
# rgb[:white] # => '#FFFFFF' # symbol retrieval
|
18
|
+
# rgb['white'] # => '#FFFFFF' # string retrieval
|
19
|
+
#
|
20
|
+
# Internally, symbols are mapped to strings when used as keys in the entire
|
21
|
+
# writing interface (calling e.g. <tt>[]=</tt>, <tt>merge</tt>). This mapping
|
22
|
+
# belongs to the public interface. For example, given:
|
23
|
+
#
|
24
|
+
# hash = Sinatra::IndifferentHash.new(:a=>1)
|
25
|
+
#
|
26
|
+
# You are guaranteed that the key is returned as a string:
|
27
|
+
#
|
28
|
+
# hash.keys # => ["a"]
|
29
|
+
#
|
30
|
+
# Technically other types of keys are accepted:
|
31
|
+
#
|
32
|
+
# hash = Sinatra::IndifferentHash.new(:a=>1)
|
33
|
+
# hash[0] = 0
|
34
|
+
# hash # => { "a"=>1, 0=>0 }
|
35
|
+
#
|
36
|
+
# But this class is intended for use cases where strings or symbols are the
|
37
|
+
# expected keys and it is convenient to understand both as the same. For
|
38
|
+
# example the +params+ hash in Sinatra.
|
39
|
+
class IndifferentHash < Hash
|
40
|
+
def self.[](*args)
|
41
|
+
new.merge!(Hash[*args])
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(*args)
|
45
|
+
args.map!(&method(:convert_value))
|
46
|
+
|
47
|
+
super(*args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def default(*args)
|
51
|
+
args.map!(&method(:convert_key))
|
52
|
+
|
53
|
+
super(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def default=(value)
|
57
|
+
super(convert_value(value))
|
58
|
+
end
|
59
|
+
|
60
|
+
def assoc(key)
|
61
|
+
super(convert_key(key))
|
62
|
+
end
|
63
|
+
|
64
|
+
def rassoc(value)
|
65
|
+
super(convert_value(value))
|
66
|
+
end
|
67
|
+
|
68
|
+
def fetch(key, *args)
|
69
|
+
args.map!(&method(:convert_value))
|
70
|
+
|
71
|
+
super(convert_key(key), *args)
|
72
|
+
end
|
73
|
+
|
74
|
+
def [](key)
|
75
|
+
super(convert_key(key))
|
76
|
+
end
|
77
|
+
|
78
|
+
def []=(key, value)
|
79
|
+
super(convert_key(key), convert_value(value))
|
80
|
+
end
|
81
|
+
|
82
|
+
alias store []=
|
83
|
+
|
84
|
+
def key(value)
|
85
|
+
super(convert_value(value))
|
86
|
+
end
|
87
|
+
|
88
|
+
def key?(key)
|
89
|
+
super(convert_key(key))
|
90
|
+
end
|
91
|
+
|
92
|
+
alias has_key? key?
|
93
|
+
alias include? key?
|
94
|
+
alias member? key?
|
95
|
+
|
96
|
+
def value?(value)
|
97
|
+
super(convert_value(value))
|
98
|
+
end
|
99
|
+
|
100
|
+
alias has_value? value?
|
101
|
+
|
102
|
+
def delete(key)
|
103
|
+
super(convert_key(key))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Added in Ruby 2.3
|
107
|
+
def dig(key, *other_keys)
|
108
|
+
super(convert_key(key), *other_keys)
|
109
|
+
end
|
110
|
+
|
111
|
+
def fetch_values(*keys)
|
112
|
+
keys.map!(&method(:convert_key))
|
113
|
+
|
114
|
+
super(*keys)
|
115
|
+
end
|
116
|
+
|
117
|
+
def slice(*keys)
|
118
|
+
keys.map!(&method(:convert_key))
|
119
|
+
|
120
|
+
self.class[super(*keys)]
|
121
|
+
end
|
122
|
+
|
123
|
+
def values_at(*keys)
|
124
|
+
keys.map!(&method(:convert_key))
|
125
|
+
|
126
|
+
super(*keys)
|
127
|
+
end
|
128
|
+
|
129
|
+
def merge!(*other_hashes)
|
130
|
+
other_hashes.each do |other_hash|
|
131
|
+
if other_hash.is_a?(self.class)
|
132
|
+
super(other_hash)
|
133
|
+
else
|
134
|
+
other_hash.each_pair do |key, value|
|
135
|
+
key = convert_key(key)
|
136
|
+
value = yield(key, self[key], value) if block_given? && key?(key)
|
137
|
+
self[key] = convert_value(value)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
alias update merge!
|
146
|
+
|
147
|
+
def merge(*other_hashes, &block)
|
148
|
+
dup.merge!(*other_hashes, &block)
|
149
|
+
end
|
150
|
+
|
151
|
+
def replace(other_hash)
|
152
|
+
super(other_hash.is_a?(self.class) ? other_hash : self.class[other_hash])
|
153
|
+
end
|
154
|
+
|
155
|
+
def transform_values(&block)
|
156
|
+
dup.transform_values!(&block)
|
157
|
+
end
|
158
|
+
|
159
|
+
def transform_values!
|
160
|
+
super
|
161
|
+
super(&method(:convert_value))
|
162
|
+
end
|
163
|
+
|
164
|
+
def transform_keys(&block)
|
165
|
+
dup.transform_keys!(&block)
|
166
|
+
end
|
167
|
+
|
168
|
+
def transform_keys!
|
169
|
+
super
|
170
|
+
super(&method(:convert_key))
|
171
|
+
end
|
172
|
+
|
173
|
+
def select(*args, &block)
|
174
|
+
return to_enum(:select) unless block_given?
|
175
|
+
|
176
|
+
dup.tap { |hash| hash.select!(*args, &block) }
|
177
|
+
end
|
178
|
+
|
179
|
+
def reject(*args, &block)
|
180
|
+
return to_enum(:reject) unless block_given?
|
181
|
+
|
182
|
+
dup.tap { |hash| hash.reject!(*args, &block) }
|
183
|
+
end
|
184
|
+
|
185
|
+
def compact
|
186
|
+
dup.tap(&:compact!)
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def convert_key(key)
|
192
|
+
key.is_a?(Symbol) ? key.to_s : key
|
193
|
+
end
|
194
|
+
|
195
|
+
def convert_value(value)
|
196
|
+
case value
|
197
|
+
when Hash
|
198
|
+
value.is_a?(self.class) ? value : self.class[value]
|
199
|
+
when Array
|
200
|
+
value.map(&method(:convert_value))
|
201
|
+
else
|
202
|
+
value
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
data/lib/sinatra/main.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
PARAMS_CONFIG = {}
|
5
|
+
|
6
|
+
if ARGV.any?
|
7
|
+
require 'optparse'
|
8
|
+
parser = OptionParser.new do |op|
|
9
|
+
op.on('-p port', 'set the port (default is 4567)') { |val| PARAMS_CONFIG[:port] = Integer(val) }
|
10
|
+
op.on('-s server', 'specify rack server/handler') { |val| PARAMS_CONFIG[:server] = val }
|
11
|
+
op.on('-q', 'turn on quiet mode (default is off)') { PARAMS_CONFIG[:quiet] = true }
|
12
|
+
op.on('-x', 'turn on the mutex lock (default is off)') { PARAMS_CONFIG[:lock] = true }
|
13
|
+
op.on('-e env', 'set the environment (default is development)') do |val|
|
14
|
+
ENV['RACK_ENV'] = val
|
15
|
+
PARAMS_CONFIG[:environment] = val.to_sym
|
16
|
+
end
|
17
|
+
op.on('-o addr', "set the host (default is (env == 'development' ? 'localhost' : '0.0.0.0'))") do |val|
|
18
|
+
PARAMS_CONFIG[:bind] = val
|
19
|
+
end
|
20
|
+
end
|
21
|
+
begin
|
22
|
+
parser.parse!(ARGV.dup)
|
23
|
+
rescue StandardError => e
|
24
|
+
PARAMS_CONFIG[:optparse_error] = e
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'sinatra/base'
|
29
|
+
|
30
|
+
class Application < Base
|
31
|
+
# we assume that the first file that requires 'sinatra' is the
|
32
|
+
# app_file. all other path related options are calculated based
|
33
|
+
# on this path by default.
|
34
|
+
set :app_file, caller_files.first || $0
|
35
|
+
|
36
|
+
set :run, proc { File.expand_path($0) == File.expand_path(app_file) }
|
37
|
+
|
38
|
+
if run? && ARGV.any?
|
39
|
+
error = PARAMS_CONFIG.delete(:optparse_error)
|
40
|
+
raise error if error
|
41
|
+
|
42
|
+
PARAMS_CONFIG.each { |k, v| set k, v }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
remove_const(:PARAMS_CONFIG)
|
47
|
+
at_exit { Application.run! if $!.nil? && Application.run? }
|
48
|
+
end
|
49
|
+
|
50
|
+
# include would include the module in Object
|
51
|
+
# extend only extends the `main` object
|
52
|
+
extend Sinatra::Delegator
|
53
|
+
|
54
|
+
class Rack::Builder
|
55
|
+
include Sinatra::Delegator
|
56
|
+
end
|
@@ -0,0 +1,364 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rack/show_exceptions'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
# Sinatra::ShowExceptions catches all exceptions raised from the app it
|
7
|
+
# wraps. It shows a useful backtrace with the sourcefile and clickable
|
8
|
+
# context, the whole Rack environment and the request data.
|
9
|
+
#
|
10
|
+
# Be careful when you use this on public-facing sites as it could reveal
|
11
|
+
# information helpful to attackers.
|
12
|
+
class ShowExceptions < Rack::ShowExceptions
|
13
|
+
@@eats_errors = Object.new
|
14
|
+
def @@eats_errors.flush(*) end
|
15
|
+
|
16
|
+
def @@eats_errors.puts(*) end
|
17
|
+
|
18
|
+
def initialize(app)
|
19
|
+
@app = app
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
@app.call(env)
|
24
|
+
rescue Exception => e
|
25
|
+
errors = env['rack.errors']
|
26
|
+
env['rack.errors'] = @@eats_errors
|
27
|
+
|
28
|
+
if prefers_plain_text?(env)
|
29
|
+
content_type = 'text/plain'
|
30
|
+
body = dump_exception(e)
|
31
|
+
else
|
32
|
+
content_type = 'text/html'
|
33
|
+
body = pretty(env, e)
|
34
|
+
end
|
35
|
+
|
36
|
+
env['rack.errors'] = errors
|
37
|
+
|
38
|
+
[
|
39
|
+
500,
|
40
|
+
{
|
41
|
+
'content-type' => content_type,
|
42
|
+
'content-length' => body.bytesize.to_s
|
43
|
+
},
|
44
|
+
[body]
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def template
|
49
|
+
TEMPLATE
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def bad_request?(exception)
|
55
|
+
Sinatra::BadRequest === exception
|
56
|
+
end
|
57
|
+
|
58
|
+
def prefers_plain_text?(env)
|
59
|
+
Request.new(env).preferred_type('text/plain', 'text/html') != 'text/html' &&
|
60
|
+
[/curl/].index { |item| item =~ env['HTTP_USER_AGENT'] }
|
61
|
+
end
|
62
|
+
|
63
|
+
def frame_class(frame)
|
64
|
+
if frame.filename =~ %r{lib/sinatra.*\.rb}
|
65
|
+
'framework'
|
66
|
+
elsif (defined?(Gem) && frame.filename.include?(Gem.dir)) ||
|
67
|
+
frame.filename =~ %r{/bin/(\w+)\z}
|
68
|
+
'system'
|
69
|
+
else
|
70
|
+
'app'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
TEMPLATE = ERB.new <<-HTML # :nodoc:
|
75
|
+
<!DOCTYPE html>
|
76
|
+
<html>
|
77
|
+
<head>
|
78
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
79
|
+
<title><%=h exception.class %> at <%=h path %></title>
|
80
|
+
|
81
|
+
<script type="text/javascript">
|
82
|
+
//<!--
|
83
|
+
function toggle(id) {
|
84
|
+
var pre = document.getElementById("pre-" + id);
|
85
|
+
var post = document.getElementById("post-" + id);
|
86
|
+
var context = document.getElementById("context-" + id);
|
87
|
+
|
88
|
+
if (pre.style.display == 'block') {
|
89
|
+
pre.style.display = 'none';
|
90
|
+
post.style.display = 'none';
|
91
|
+
context.style.background = "none";
|
92
|
+
} else {
|
93
|
+
pre.style.display = 'block';
|
94
|
+
post.style.display = 'block';
|
95
|
+
context.style.background = "#fffed9";
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
function toggleBacktrace(){
|
100
|
+
var bt = document.getElementById("backtrace");
|
101
|
+
var toggler = document.getElementById("expando");
|
102
|
+
|
103
|
+
if (bt.className == 'condensed') {
|
104
|
+
bt.className = 'expanded';
|
105
|
+
toggler.innerHTML = "(condense)";
|
106
|
+
} else {
|
107
|
+
bt.className = 'condensed';
|
108
|
+
toggler.innerHTML = "(expand)";
|
109
|
+
}
|
110
|
+
}
|
111
|
+
//-->
|
112
|
+
</script>
|
113
|
+
|
114
|
+
<style type="text/css" media="screen">
|
115
|
+
* {margin: 0; padding: 0; border: 0; outline: 0;}
|
116
|
+
div.clear {clear: both;}
|
117
|
+
body {background: #EEEEEE; margin: 0; padding: 0;
|
118
|
+
font-family: 'Lucida Grande', 'Lucida Sans Unicode',
|
119
|
+
'Garuda';}
|
120
|
+
code {font-family: 'Lucida Console', monospace;
|
121
|
+
font-size: 12px;}
|
122
|
+
li {height: 18px;}
|
123
|
+
ul {list-style: none; margin: 0; padding: 0;}
|
124
|
+
ol:hover {cursor: pointer;}
|
125
|
+
ol li {white-space: pre;}
|
126
|
+
#explanation {font-size: 12px; color: #666666;
|
127
|
+
margin: 20px 0 0 100px;}
|
128
|
+
/* WRAP */
|
129
|
+
#wrap {width: 1000px; background: #FFFFFF; margin: 0 auto;
|
130
|
+
padding: 30px 50px 20px 50px;
|
131
|
+
border-left: 1px solid #DDDDDD;
|
132
|
+
border-right: 1px solid #DDDDDD;}
|
133
|
+
/* HEADER */
|
134
|
+
#header {margin: 0 auto 25px auto;}
|
135
|
+
#header img {float: left;}
|
136
|
+
#header #summary {float: left; margin: 12px 0 0 20px; width:660px;
|
137
|
+
font-family: 'Lucida Grande', 'Lucida Sans Unicode';}
|
138
|
+
h1 {margin: 0; font-size: 36px; color: #981919;}
|
139
|
+
h2 {margin: 0; font-size: 22px; color: #333333;}
|
140
|
+
#header ul {margin: 0; font-size: 12px; color: #666666;}
|
141
|
+
#header ul li strong{color: #444444;}
|
142
|
+
#header ul li {display: inline; padding: 0 10px;}
|
143
|
+
#header ul li.first {padding-left: 0;}
|
144
|
+
#header ul li.last {border: 0; padding-right: 0;}
|
145
|
+
/* BODY */
|
146
|
+
#backtrace,
|
147
|
+
#get,
|
148
|
+
#post,
|
149
|
+
#cookies,
|
150
|
+
#rack {width: 980px; margin: 0 auto 10px auto;}
|
151
|
+
p#nav {float: right; font-size: 14px;}
|
152
|
+
/* BACKTRACE */
|
153
|
+
a#expando {float: left; padding-left: 5px; color: #666666;
|
154
|
+
font-size: 14px; text-decoration: none; cursor: pointer;}
|
155
|
+
a#expando:hover {text-decoration: underline;}
|
156
|
+
h3 {float: left; width: 100px; margin-bottom: 10px;
|
157
|
+
color: #981919; font-size: 14px; font-weight: bold;}
|
158
|
+
#nav a {color: #666666; text-decoration: none; padding: 0 5px;}
|
159
|
+
#backtrace li.frame-info {background: #f7f7f7; padding-left: 10px;
|
160
|
+
font-size: 12px; color: #333333;}
|
161
|
+
#backtrace ul {list-style-position: outside; border: 1px solid #E9E9E9;
|
162
|
+
border-bottom: 0;}
|
163
|
+
#backtrace ol {width: 920px; margin-left: 50px;
|
164
|
+
font: 10px 'Lucida Console', monospace; color: #666666;}
|
165
|
+
#backtrace ol li {border: 0; border-left: 1px solid #E9E9E9;
|
166
|
+
padding: 2px 0;}
|
167
|
+
#backtrace ol code {font-size: 10px; color: #555555; padding-left: 5px;}
|
168
|
+
#backtrace-ul li {border-bottom: 1px solid #E9E9E9; height: auto;
|
169
|
+
padding: 3px 0;}
|
170
|
+
#backtrace-ul .code {padding: 6px 0 4px 0;}
|
171
|
+
#backtrace.condensed .system,
|
172
|
+
#backtrace.condensed .framework {display:none;}
|
173
|
+
/* REQUEST DATA */
|
174
|
+
p.no-data {padding-top: 2px; font-size: 12px; color: #666666;}
|
175
|
+
table.req {width: 980px; text-align: left; font-size: 12px;
|
176
|
+
color: #666666; padding: 0; border-spacing: 0;
|
177
|
+
border: 1px solid #EEEEEE; border-bottom: 0;
|
178
|
+
border-left: 0;
|
179
|
+
clear:both}
|
180
|
+
table.req tr th {padding: 2px 10px; font-weight: bold;
|
181
|
+
background: #F7F7F7; border-bottom: 1px solid #EEEEEE;
|
182
|
+
border-left: 1px solid #EEEEEE;}
|
183
|
+
table.req tr td {padding: 2px 20px 2px 10px;
|
184
|
+
border-bottom: 1px solid #EEEEEE;
|
185
|
+
border-left: 1px solid #EEEEEE;}
|
186
|
+
/* HIDE PRE/POST CODE AT START */
|
187
|
+
.pre-context,
|
188
|
+
.post-context {display: none;}
|
189
|
+
|
190
|
+
table td.code {width:750px}
|
191
|
+
table td.code div {width:750px;overflow:hidden}
|
192
|
+
</style>
|
193
|
+
</head>
|
194
|
+
<body>
|
195
|
+
<div id="wrap">
|
196
|
+
<div id="header">
|
197
|
+
<img src="<%= env['SCRIPT_NAME'] %>/__sinatra__/500.png" alt="application error" height="161" width="313" />
|
198
|
+
<div id="summary">
|
199
|
+
<h1><strong><%=h exception.class %></strong> at <strong><%=h path %>
|
200
|
+
</strong></h1>
|
201
|
+
<h2><%=h exception.message %></h2>
|
202
|
+
<ul>
|
203
|
+
<li class="first"><strong>file:</strong> <code>
|
204
|
+
<%=h frames.first.filename.split("/").last %></code></li>
|
205
|
+
<li><strong>location:</strong> <code><%=h frames.first.function %>
|
206
|
+
</code></li>
|
207
|
+
<li class="last"><strong>line:
|
208
|
+
</strong> <%=h frames.first.lineno %></li>
|
209
|
+
</ul>
|
210
|
+
</div>
|
211
|
+
<div class="clear"></div>
|
212
|
+
</div>
|
213
|
+
|
214
|
+
<div id="backtrace" class='condensed'>
|
215
|
+
<h3>BACKTRACE</h3>
|
216
|
+
<p><a href="#" id="expando"
|
217
|
+
onclick="toggleBacktrace(); return false">(expand)</a></p>
|
218
|
+
<p id="nav"><strong>JUMP TO:</strong>
|
219
|
+
<% unless bad_request?(exception) %>
|
220
|
+
<a href="#get-info">GET</a>
|
221
|
+
<a href="#post-info">POST</a>
|
222
|
+
<% end %>
|
223
|
+
<a href="#cookie-info">COOKIES</a>
|
224
|
+
<a href="#env-info">ENV</a>
|
225
|
+
</p>
|
226
|
+
<div class="clear"></div>
|
227
|
+
|
228
|
+
<ul id="backtrace-ul">
|
229
|
+
|
230
|
+
<% id = 1 %>
|
231
|
+
<% frames.each do |frame| %>
|
232
|
+
<% if frame.context_line && frame.context_line != "#" %>
|
233
|
+
|
234
|
+
<li class="frame-info <%= frame_class(frame) %>">
|
235
|
+
<code><%=h frame.filename %></code> in
|
236
|
+
<code><strong><%=h frame.function %></strong></code>
|
237
|
+
</li>
|
238
|
+
|
239
|
+
<li class="code <%= frame_class(frame) %>">
|
240
|
+
<% if frame.pre_context %>
|
241
|
+
<ol start="<%=h frame.pre_context_lineno + 1 %>"
|
242
|
+
class="pre-context" id="pre-<%= id %>"
|
243
|
+
onclick="toggle(<%= id %>);">
|
244
|
+
<% frame.pre_context.each do |line| %>
|
245
|
+
<li class="pre-context-line"><code><%=h line %></code></li>
|
246
|
+
<% end %>
|
247
|
+
</ol>
|
248
|
+
<% end %>
|
249
|
+
|
250
|
+
<ol start="<%= frame.lineno %>" class="context" id="<%= id %>"
|
251
|
+
onclick="toggle(<%= id %>);">
|
252
|
+
<li class="context-line" id="context-<%= id %>"><code><%=
|
253
|
+
h frame.context_line %></code></li>
|
254
|
+
</ol>
|
255
|
+
|
256
|
+
<% if frame.post_context %>
|
257
|
+
<ol start="<%=h frame.lineno + 1 %>" class="post-context"
|
258
|
+
id="post-<%= id %>" onclick="toggle(<%= id %>);">
|
259
|
+
<% frame.post_context.each do |line| %>
|
260
|
+
<li class="post-context-line"><code><%=h line %></code></li>
|
261
|
+
<% end %>
|
262
|
+
</ol>
|
263
|
+
<% end %>
|
264
|
+
<div class="clear"></div>
|
265
|
+
</li>
|
266
|
+
|
267
|
+
<% end %>
|
268
|
+
|
269
|
+
<% id += 1 %>
|
270
|
+
<% end %>
|
271
|
+
|
272
|
+
</ul>
|
273
|
+
</div> <!-- /BACKTRACE -->
|
274
|
+
|
275
|
+
<% unless bad_request?(exception) %>
|
276
|
+
<div id="get">
|
277
|
+
<h3 id="get-info">GET</h3>
|
278
|
+
<% if req.GET and not req.GET.empty? %>
|
279
|
+
<table class="req">
|
280
|
+
<tr>
|
281
|
+
<th>Variable</th>
|
282
|
+
<th>Value</th>
|
283
|
+
</tr>
|
284
|
+
<% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
285
|
+
<tr>
|
286
|
+
<td><%=h key %></td>
|
287
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
288
|
+
</tr>
|
289
|
+
<% } %>
|
290
|
+
</table>
|
291
|
+
<% else %>
|
292
|
+
<p class="no-data">No GET data.</p>
|
293
|
+
<% end %>
|
294
|
+
<div class="clear"></div>
|
295
|
+
</div> <!-- /GET -->
|
296
|
+
|
297
|
+
<div id="post">
|
298
|
+
<h3 id="post-info">POST</h3>
|
299
|
+
<% if req.POST and not req.POST.empty? %>
|
300
|
+
<table class="req">
|
301
|
+
<tr>
|
302
|
+
<th>Variable</th>
|
303
|
+
<th>Value</th>
|
304
|
+
</tr>
|
305
|
+
<% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
306
|
+
<tr>
|
307
|
+
<td><%=h key %></td>
|
308
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
309
|
+
</tr>
|
310
|
+
<% } %>
|
311
|
+
</table>
|
312
|
+
<% else %>
|
313
|
+
<p class="no-data">No POST data.</p>
|
314
|
+
<% end %>
|
315
|
+
<div class="clear"></div>
|
316
|
+
</div> <!-- /POST -->
|
317
|
+
<% end %>
|
318
|
+
|
319
|
+
<div id="cookies">
|
320
|
+
<h3 id="cookie-info">COOKIES</h3>
|
321
|
+
<% unless req.cookies.empty? %>
|
322
|
+
<table class="req">
|
323
|
+
<tr>
|
324
|
+
<th>Variable</th>
|
325
|
+
<th>Value</th>
|
326
|
+
</tr>
|
327
|
+
<% req.cookies.each { |key, val| %>
|
328
|
+
<tr>
|
329
|
+
<td><%=h key %></td>
|
330
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
331
|
+
</tr>
|
332
|
+
<% } %>
|
333
|
+
</table>
|
334
|
+
<% else %>
|
335
|
+
<p class="no-data">No cookie data.</p>
|
336
|
+
<% end %>
|
337
|
+
<div class="clear"></div>
|
338
|
+
</div> <!-- /COOKIES -->
|
339
|
+
|
340
|
+
<div id="rack">
|
341
|
+
<h3 id="env-info">Rack ENV</h3>
|
342
|
+
<table class="req">
|
343
|
+
<tr>
|
344
|
+
<th>Variable</th>
|
345
|
+
<th>Value</th>
|
346
|
+
</tr>
|
347
|
+
<% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
348
|
+
<tr>
|
349
|
+
<td><%=h key %></td>
|
350
|
+
<td class="code"><div><%=h val %></div></td>
|
351
|
+
</tr>
|
352
|
+
<% } %>
|
353
|
+
</table>
|
354
|
+
<div class="clear"></div>
|
355
|
+
</div> <!-- /RACK ENV -->
|
356
|
+
|
357
|
+
<p id="explanation">You're seeing this error because you have
|
358
|
+
enabled the <code>show_exceptions</code> setting.</p>
|
359
|
+
</div> <!-- /WRAP -->
|
360
|
+
</body>
|
361
|
+
</html>
|
362
|
+
HTML
|
363
|
+
end
|
364
|
+
end
|
data/lib/sinatra.rb
ADDED
data/sinatra.gemspec
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
version = File.read(File.expand_path('VERSION', __dir__)).strip
|
4
|
+
|
5
|
+
Gem::Specification.new 'sinatra-rack-3-commonlit', version do |s|
|
6
|
+
s.description = 'Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort.'
|
7
|
+
s.summary = 'Classy web-development dressed in a DSL'
|
8
|
+
s.authors = ['Blake Mizerany', 'Ryan Tomayko', 'Simon Rozet', 'Konstantin Haase']
|
9
|
+
s.email = 'sinatrarb@googlegroups.com'
|
10
|
+
s.homepage = 'http://sinatrarb.com/'
|
11
|
+
s.license = 'MIT'
|
12
|
+
s.files = Dir['README*.md', 'lib/**/*', 'examples/*'] + [
|
13
|
+
'.yardopts',
|
14
|
+
'AUTHORS.md',
|
15
|
+
'CHANGELOG.md',
|
16
|
+
'CONTRIBUTING.md',
|
17
|
+
'Gemfile',
|
18
|
+
'LICENSE',
|
19
|
+
'MAINTENANCE.md',
|
20
|
+
'Rakefile',
|
21
|
+
'SECURITY.md',
|
22
|
+
'sinatra.gemspec',
|
23
|
+
'VERSION'
|
24
|
+
]
|
25
|
+
s.extra_rdoc_files = %w[README.md LICENSE]
|
26
|
+
s.rdoc_options = %w[--line-numbers --title Sinatra --main README.rdoc --encoding=UTF-8]
|
27
|
+
|
28
|
+
unless s.respond_to?(:metadata)
|
29
|
+
raise <<-WARN
|
30
|
+
RubyGems 2.0 or newer is required to protect against public gem pushes. You can update your rubygems version by running:
|
31
|
+
gem install rubygems-update
|
32
|
+
update_rubygems:
|
33
|
+
gem update --system
|
34
|
+
WARN
|
35
|
+
end
|
36
|
+
|
37
|
+
s.metadata = {
|
38
|
+
'source_code_uri' => 'https://github.com/sinatra/sinatra',
|
39
|
+
'changelog_uri' => 'https://github.com/sinatra/sinatra/blob/main/CHANGELOG.md',
|
40
|
+
'homepage_uri' => 'http://sinatrarb.com/',
|
41
|
+
'bug_tracker_uri' => 'https://github.com/sinatra/sinatra/issues',
|
42
|
+
'mailing_list_uri' => 'http://groups.google.com/group/sinatrarb',
|
43
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/sinatra'
|
44
|
+
}
|
45
|
+
|
46
|
+
s.required_ruby_version = '>= 2.6.0'
|
47
|
+
|
48
|
+
s.add_dependency 'mustermann', '~> 3.0'
|
49
|
+
s.add_dependency 'rack', '>= 3.0.0.beta1', '< 4'
|
50
|
+
s.add_dependency 'rackup', '>= 2.0.0', '< 3'
|
51
|
+
s.add_dependency 'rack-session', '>= 2.0.0', '< 3'
|
52
|
+
s.add_dependency 'rack-protection', version
|
53
|
+
s.add_dependency 'tilt', '~> 2.0'
|
54
|
+
|
55
|
+
s.add_development_dependency 'rack-test', '~> 2'
|
56
|
+
end
|