sinatra-rack-3-commonlit 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|