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
data/Rakefile
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'minitest/test_task'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'date'
|
7
|
+
|
8
|
+
task default: :test
|
9
|
+
|
10
|
+
def source_version
|
11
|
+
@source_version ||= File.read(File.expand_path('VERSION', __dir__)).strip
|
12
|
+
end
|
13
|
+
|
14
|
+
def prev_feature
|
15
|
+
source_version.gsub(/^(\d\.)(\d+)\..*$/) { $1 + ($2.to_i - 1).to_s }
|
16
|
+
end
|
17
|
+
|
18
|
+
def prev_version
|
19
|
+
return "#{prev_feature}.0" if source_version.end_with? '.0'
|
20
|
+
|
21
|
+
source_version.gsub(/\d+$/) { |s| s.to_i - 1 }
|
22
|
+
end
|
23
|
+
|
24
|
+
# Tests ===============================================================
|
25
|
+
|
26
|
+
Minitest::TestTask.create # Default `test` task
|
27
|
+
Minitest::TestTask.create(:'test:core') do |t|
|
28
|
+
t.warning = true
|
29
|
+
t.test_globs = %w[
|
30
|
+
base delegator encoding extensions filter
|
31
|
+
helpers mapped_error middleware rdoc
|
32
|
+
readme request response result route_added_hook
|
33
|
+
routing server settings sinatra static templates
|
34
|
+
].map { |n| "test/#{n}_test.rb" }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Test code coverage ==================================================
|
38
|
+
|
39
|
+
namespace :test do
|
40
|
+
desc 'Measures test coverage'
|
41
|
+
task :coverage do
|
42
|
+
rm_f 'coverage'
|
43
|
+
ENV['COVERAGE'] = '1'
|
44
|
+
Rake::Task['test'].invoke
|
45
|
+
end
|
46
|
+
end
|
47
|
+
CLEAN.include('coverage')
|
48
|
+
|
49
|
+
# Website =============================================================
|
50
|
+
|
51
|
+
desc 'Generate RDoc under doc/api'
|
52
|
+
task 'doc' => ['doc:api']
|
53
|
+
task('doc:api') { sh 'yardoc -o doc/api' }
|
54
|
+
CLEAN.include 'doc/api'
|
55
|
+
|
56
|
+
# README ===============================================================
|
57
|
+
|
58
|
+
task :add_template, [:name] do |_t, args|
|
59
|
+
Dir.glob('README.*') do |file|
|
60
|
+
code = File.read(file)
|
61
|
+
if code =~ /^===.*#{args.name.capitalize}/
|
62
|
+
puts "Already covered in #{file}"
|
63
|
+
else
|
64
|
+
template = code[%r{===[^\n]*Liquid.*index\.liquid</tt>[^\n]*}m]
|
65
|
+
if template
|
66
|
+
puts "Adding section to #{file}"
|
67
|
+
template = template.gsub(/Liquid/, args.name.capitalize).gsub(/liquid/, args.name.downcase)
|
68
|
+
code.gsub! /^(\s*===.*CoffeeScript)/, "\n" << template << "\n\\1"
|
69
|
+
File.open(file, 'w') { |f| f << code }
|
70
|
+
else
|
71
|
+
puts "Liquid not found in #{file}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Thanks in announcement ===============================================
|
78
|
+
|
79
|
+
team = ['Ryan Tomayko', 'Blake Mizerany', 'Simon Rozet', 'Konstantin Haase', 'Zachary Scott']
|
80
|
+
desc 'list of contributors'
|
81
|
+
task :thanks, ['release:all', :backports] do |_t, a|
|
82
|
+
a.with_defaults release: "#{prev_version}..HEAD",
|
83
|
+
backports: "#{prev_feature}.0..#{prev_feature}.x"
|
84
|
+
|
85
|
+
included = `git log --format=format:"%aN\t%s" #{a.release}`.lines.map { |l| l.force_encoding('binary') }
|
86
|
+
excluded = `git log --format=format:"%aN\t%s" #{a.backports}`.lines.map { |l| l.force_encoding('binary') }
|
87
|
+
commits = (included - excluded).group_by { |c| c[/^[^\t]+/] }
|
88
|
+
authors = commits.keys.sort_by { |n| - commits[n].size } - team
|
89
|
+
puts authors[0..-2].join(', ') << ' and ' << authors.last,
|
90
|
+
"(based on commits included in #{a.release}, but not in #{a.backports})"
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'list of authors'
|
94
|
+
task :authors, [:commit_range, :format, :sep] do |_t, a|
|
95
|
+
a.with_defaults format: '%s (%d)', sep: ', ', commit_range: '--all'
|
96
|
+
authors = Hash.new(0)
|
97
|
+
blake = 'Blake Mizerany'
|
98
|
+
overall = 0
|
99
|
+
mapping = {
|
100
|
+
'blake.mizerany@gmail.com' => blake, 'bmizerany' => blake,
|
101
|
+
'a_user@mac.com' => blake, 'ichverstehe' => 'Harry Vangberg',
|
102
|
+
'Wu Jiang (nouse)' => 'Wu Jiang'
|
103
|
+
}
|
104
|
+
`git shortlog -s #{a.commit_range}`.lines.map do |line|
|
105
|
+
line = line.force_encoding 'binary' if line.respond_to? :force_encoding
|
106
|
+
num, name = line.split("\t", 2).map(&:strip)
|
107
|
+
authors[mapping[name] || name] += num.to_i
|
108
|
+
overall += num.to_i
|
109
|
+
end
|
110
|
+
puts "#{overall} commits by #{authors.count} authors:"
|
111
|
+
puts authors.sort_by { |_n, c| -c }.map { |e| a.format % e }.join(a.sep)
|
112
|
+
end
|
113
|
+
|
114
|
+
desc 'generates TOC'
|
115
|
+
task :toc, [:readme] do |_t, a|
|
116
|
+
a.with_defaults readme: 'README.md'
|
117
|
+
|
118
|
+
def self.link(title)
|
119
|
+
title.downcase.gsub(/(?!-)\W /, '-').gsub(' ', '-').gsub(/(?!-)\W/, '')
|
120
|
+
end
|
121
|
+
|
122
|
+
puts '* [Sinatra](#sinatra)'
|
123
|
+
title = Regexp.new('(?<=\* )(.*)') # so Ruby 1.8 doesn't complain
|
124
|
+
File.binread(a.readme).scan(/^##.*/) do |line|
|
125
|
+
puts line.gsub(/#(?=#)/, ' ').gsub('#', '*').gsub(title) { "[#{$1}](##{link($1)})" }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# PACKAGING ============================================================
|
130
|
+
|
131
|
+
if defined?(Gem)
|
132
|
+
GEMS_AND_ROOT_DIRECTORIES = {
|
133
|
+
'sinatra' => '.',
|
134
|
+
'sinatra-contrib' => './sinatra-contrib',
|
135
|
+
'rack-protection' => './rack-protection'
|
136
|
+
}.freeze
|
137
|
+
|
138
|
+
def package(gem, ext = '')
|
139
|
+
"pkg/#{gem}-#{source_version}" + ext
|
140
|
+
end
|
141
|
+
|
142
|
+
directory 'pkg/'
|
143
|
+
CLOBBER.include('pkg')
|
144
|
+
|
145
|
+
GEMS_AND_ROOT_DIRECTORIES.each do |gem, directory|
|
146
|
+
file package(gem, '.gem') => ['pkg/', "#{"#{directory}/#{gem}"}.gemspec"] do |f|
|
147
|
+
sh "cd #{directory} && gem build #{gem}.gemspec"
|
148
|
+
mv "#{directory}/#{File.basename(f.name)}", f.name
|
149
|
+
end
|
150
|
+
|
151
|
+
file package(gem, '.tar.gz') => ['pkg/'] do |f|
|
152
|
+
sh <<-SH
|
153
|
+
git archive \
|
154
|
+
--prefix=#{gem}-#{source_version}/ \
|
155
|
+
--format=tar \
|
156
|
+
HEAD -- #{directory} | gzip > #{f.name}
|
157
|
+
SH
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
namespace :package do
|
162
|
+
GEMS_AND_ROOT_DIRECTORIES.each do |gem, _directory|
|
163
|
+
desc "Build #{gem} packages"
|
164
|
+
task gem => %w[.gem .tar.gz].map { |e| package(gem, e) }
|
165
|
+
end
|
166
|
+
|
167
|
+
desc 'Build all packages'
|
168
|
+
task all: GEMS_AND_ROOT_DIRECTORIES.keys
|
169
|
+
end
|
170
|
+
|
171
|
+
namespace :install do
|
172
|
+
GEMS_AND_ROOT_DIRECTORIES.each do |gem, _directory|
|
173
|
+
desc "Build and install #{gem} as local gem"
|
174
|
+
task gem => package(gem, '.gem') do
|
175
|
+
sh "gem install #{package(gem, '.gem')}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
desc 'Build and install all of the gems as local gems'
|
180
|
+
task all: GEMS_AND_ROOT_DIRECTORIES.keys
|
181
|
+
end
|
182
|
+
|
183
|
+
namespace :release do
|
184
|
+
GEMS_AND_ROOT_DIRECTORIES.each do |gem, _directory|
|
185
|
+
desc "Release #{gem} as a package"
|
186
|
+
task gem => "package:#{gem}" do
|
187
|
+
sh <<-SH
|
188
|
+
gem install #{package(gem, '.gem')} --local &&
|
189
|
+
gem push #{package(gem, '.gem')}
|
190
|
+
SH
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
desc 'Commits the version to github repository'
|
195
|
+
task :commit_version do
|
196
|
+
%w[
|
197
|
+
lib/sinatra
|
198
|
+
sinatra-contrib/lib/sinatra/contrib
|
199
|
+
rack-protection/lib/rack/protection
|
200
|
+
].each do |path|
|
201
|
+
path = File.join(path, 'version.rb')
|
202
|
+
File.write(path, File.read(path).sub(/VERSION = '(.+?)'/, "VERSION = '#{source_version}'"))
|
203
|
+
end
|
204
|
+
|
205
|
+
sh <<-SH
|
206
|
+
git commit --allow-empty -a -m '#{source_version} release' &&
|
207
|
+
git tag -s v#{source_version} -m '#{source_version} release' &&
|
208
|
+
git push && (git push origin || true) &&
|
209
|
+
git push --tags && (git push origin --tags || true)
|
210
|
+
SH
|
211
|
+
end
|
212
|
+
|
213
|
+
desc 'Release all gems as packages'
|
214
|
+
task all: %i[test commit_version] + GEMS_AND_ROOT_DIRECTORIES.keys
|
215
|
+
end
|
216
|
+
end
|
data/SECURITY.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Reporting a security bug
|
2
|
+
|
3
|
+
All security bugs in Sinatra should be reported to the core team through our private mailing list [sinatra-security@googlegroups.com](https://groups.google.com/group/sinatra-security). Your report will be acknowledged within 24 hours, and you’ll receive a more detailed response to your email within 48 hours indicating the next steps in handling your report.
|
4
|
+
|
5
|
+
After the initial reply to your report the security team will endeavor to keep you informed of the progress being made towards a fix and full announcement. These updates will be sent at least every five days, in reality this is more likely to be every 24-48 hours.
|
6
|
+
|
7
|
+
If you have not received a reply to your email within 48 hours, or have not heard from the security team for the past five days there are a few steps you can take:
|
8
|
+
|
9
|
+
* Contact the current security coordinator [Zachary Scott](mailto:zzak@ruby-lang.org) directly
|
10
|
+
|
11
|
+
## Disclosure Policy
|
12
|
+
|
13
|
+
Sinatra has a 5 step disclosure policy, that is upheld to the best of our ability.
|
14
|
+
|
15
|
+
1. Security report received and is assigned a primary handler. This person will coordinate the fix and release process.
|
16
|
+
2. Problem is confirmed and, a list of all affected versions is determined. Code is audited to find any potential similar problems.
|
17
|
+
3. Fixes are prepared for all releases which are still supported. These fixes are not committed to the public repository but rather held locally pending the announcement.
|
18
|
+
4. A suggested embargo date for this vulnerability is chosen and distros@openwall is notified. This notification will include patches for all versions still under support and a contact address for packagers who need advice back-porting patches to older versions.
|
19
|
+
5. On the embargo date, the [mailing list][mailing-list] and [security list][security-list] are sent a copy of the announcement. The changes are pushed to the public repository and new gems released to rubygems.
|
20
|
+
|
21
|
+
Typically the embargo date will be set 72 hours from the time vendor-sec is first notified, however this may vary depending on the severity of the bug or difficulty in applying a fix.
|
22
|
+
|
23
|
+
This process can take some time, especially when coordination is required with maintainers of other projects. Every effort will be made to handle the bug in as timely a manner as possible, however it’s important that we follow the release process above to ensure that the disclosure is handled in a consistent manner.
|
24
|
+
|
25
|
+
## Security Updates
|
26
|
+
|
27
|
+
Security updates will be posted on the [mailing list][mailing-list] and [security list][security-list].
|
28
|
+
|
29
|
+
## Comments on this Policy
|
30
|
+
|
31
|
+
If you have any suggestions to improve this policy, please send an email the core team at [sinatrarb@googlegroups.com](https://groups.google.com/group/sinatrarb).
|
32
|
+
|
33
|
+
|
34
|
+
[mailing-list]: http://groups.google.com/group/sinatrarb/topics
|
35
|
+
[security-list]: http://groups.google.com/group/sinatra-security/topics
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.0
|
data/examples/chat.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby -I ../lib -I lib
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# This example does *not* work properly with WEBrick or other
|
5
|
+
# servers that buffer output. To shut down the server, close any
|
6
|
+
# open browser tabs that are connected to the chat server.
|
7
|
+
|
8
|
+
require 'sinatra'
|
9
|
+
set :server, :puma
|
10
|
+
connections = Set.new
|
11
|
+
|
12
|
+
get '/' do
|
13
|
+
halt erb(:login) unless params[:user]
|
14
|
+
erb :chat, locals: { user: params[:user].gsub(/\W/, '') }
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/stream', provides: 'text/event-stream' do
|
18
|
+
stream :keep_open do |out|
|
19
|
+
if connections.add?(out)
|
20
|
+
out.callback { connections.delete(out) }
|
21
|
+
end
|
22
|
+
out << "heartbeat:\n"
|
23
|
+
sleep 1
|
24
|
+
rescue
|
25
|
+
out.close
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
post '/' do
|
30
|
+
connections.each do |out|
|
31
|
+
out << "data: #{params[:msg]}\n\n"
|
32
|
+
rescue
|
33
|
+
out.close
|
34
|
+
end
|
35
|
+
204 # response without entity body
|
36
|
+
end
|
37
|
+
|
38
|
+
__END__
|
39
|
+
|
40
|
+
@@ layout
|
41
|
+
<html>
|
42
|
+
<head>
|
43
|
+
<title>Super Simple Chat with Sinatra</title>
|
44
|
+
<meta charset="utf-8" />
|
45
|
+
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
|
46
|
+
</head>
|
47
|
+
<body><%= yield %></body>
|
48
|
+
</html>
|
49
|
+
|
50
|
+
@@ login
|
51
|
+
<form action="/">
|
52
|
+
<label for='user'>User Name:</label>
|
53
|
+
<input name="user" value="" />
|
54
|
+
<input type="submit" value="GO!" />
|
55
|
+
</form>
|
56
|
+
|
57
|
+
@@ chat
|
58
|
+
<pre id='chat'></pre>
|
59
|
+
<form>
|
60
|
+
<input id='msg' placeholder='type message here...' />
|
61
|
+
</form>
|
62
|
+
|
63
|
+
<script>
|
64
|
+
// reading
|
65
|
+
var es = new EventSource('/stream');
|
66
|
+
es.onmessage = function(e) { $('#chat').append(e.data + "\n") };
|
67
|
+
|
68
|
+
// writing
|
69
|
+
$("form").on('submit',function(e) {
|
70
|
+
$.post('/', {msg: "<%= user %>: " + $('#msg').val()});
|
71
|
+
$('#msg').val(''); $('#msg').focus();
|
72
|
+
e.preventDefault();
|
73
|
+
});
|
74
|
+
</script>
|
75
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby -I ../lib -I lib
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'sinatra'
|
5
|
+
|
6
|
+
get('/') do
|
7
|
+
'This shows how lifecycle events work'
|
8
|
+
end
|
9
|
+
|
10
|
+
on_start do
|
11
|
+
puts "=============="
|
12
|
+
puts " Booting up"
|
13
|
+
puts "=============="
|
14
|
+
end
|
15
|
+
|
16
|
+
on_stop do
|
17
|
+
puts "================="
|
18
|
+
puts " Shutting down"
|
19
|
+
puts "================="
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rainbows'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
module Handler
|
7
|
+
class Rainbows
|
8
|
+
def self.run(app, **options)
|
9
|
+
rainbows_options = {
|
10
|
+
listeners: ["#{options[:Host]}:#{options[:Port]}"],
|
11
|
+
worker_processes: 1,
|
12
|
+
timeout: 30,
|
13
|
+
config_file: ::File.expand_path('rainbows.conf', __dir__)
|
14
|
+
}
|
15
|
+
|
16
|
+
::Rainbows::HttpServer.new(app, rainbows_options).start.join
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
register :rainbows, ::Rack::Handler::Rainbows
|
21
|
+
end
|
22
|
+
end
|
data/examples/simple.rb
ADDED
data/examples/stream.ru
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this example does *not* work properly with WEBrick
|
4
|
+
#
|
5
|
+
# run *one* of these:
|
6
|
+
#
|
7
|
+
# unicorn stream.ru # gem install unicorn
|
8
|
+
# puma stream.ru # gem install puma
|
9
|
+
# rainbows -c rainbows.conf stream.ru # gem install rainbows eventmachine
|
10
|
+
|
11
|
+
require 'sinatra/base'
|
12
|
+
|
13
|
+
class Stream < Sinatra::Base
|
14
|
+
get '/' do
|
15
|
+
content_type :txt
|
16
|
+
|
17
|
+
stream do |out|
|
18
|
+
out << "It's gonna be legen -\n"
|
19
|
+
sleep 0.5
|
20
|
+
out << " (wait for it) \n"
|
21
|
+
sleep 1
|
22
|
+
out << "- dary!\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
run Stream
|