diy_rails 0.1.0 → 0.2.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 +4 -4
- data/Gemfile.lock +5 -2
- data/lib/diy_rails/array.rb +5 -0
- data/lib/diy_rails/routing.rb +10 -0
- data/lib/diy_rails/version.rb +1 -1
- data/lib/diy_rails.rb +25 -3
- metadata +28 -151
- data/vendor/bundle/ruby/3.0.0/bin/rackup +0 -29
- data/vendor/bundle/ruby/3.0.0/bin/rake +0 -29
- data/vendor/bundle/ruby/3.0.0/cache/rack-2.2.4.gem +0 -0
- data/vendor/bundle/ruby/3.0.0/cache/rake-13.0.6.gem +0 -0
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/CHANGELOG.md +0 -708
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/CONTRIBUTING.md +0 -136
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/MIT-LICENSE +0 -20
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/README.rdoc +0 -306
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/Rakefile +0 -130
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/SPEC.rdoc +0 -288
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/bin/rackup +0 -5
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack.png +0 -0
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack.svg +0 -150
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rack_logo.svg +0 -164
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/contrib/rdoc.css +0 -412
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/lobster.ru +0 -6
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/protectedlobster.rb +0 -16
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/example/protectedlobster.ru +0 -10
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/abstract/handler.rb +0 -39
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/abstract/request.rb +0 -47
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/basic.rb +0 -61
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/md5.rb +0 -131
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/nonce.rb +0 -54
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/params.rb +0 -54
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/auth/digest/request.rb +0 -43
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/body_proxy.rb +0 -45
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/builder.rb +0 -257
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/cascade.rb +0 -68
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/chunked.rb +0 -117
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/common_logger.rb +0 -83
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/conditional_get.rb +0 -83
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/config.rb +0 -22
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/content_length.rb +0 -38
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/content_type.rb +0 -30
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/core_ext/regexp.rb +0 -14
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/deflater.rb +0 -144
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/directory.rb +0 -199
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/etag.rb +0 -77
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/events.rb +0 -153
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/file.rb +0 -7
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/files.rb +0 -218
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/cgi.rb +0 -59
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/fastcgi.rb +0 -100
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/lsws.rb +0 -61
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/scgi.rb +0 -71
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/thin.rb +0 -36
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler/webrick.rb +0 -129
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/handler.rb +0 -104
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/head.rb +0 -25
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lint.rb +0 -806
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lobster.rb +0 -70
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/lock.rb +0 -32
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/logger.rb +0 -20
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/media_type.rb +0 -43
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/method_override.rb +0 -52
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/mime.rb +0 -685
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/mock.rb +0 -273
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/generator.rb +0 -97
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/parser.rb +0 -365
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart/uploaded_file.rb +0 -41
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/multipart.rb +0 -64
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/null_logger.rb +0 -39
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/query_parser.rb +0 -221
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/recursive.rb +0 -64
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/reloader.rb +0 -114
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/request.rb +0 -659
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/response.rb +0 -318
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/rewindable_input.rb +0 -94
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/runtime.rb +0 -34
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/sendfile.rb +0 -162
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/server.rb +0 -466
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/abstract/id.rb +0 -523
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/cookie.rb +0 -203
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/memcache.rb +0 -10
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/session/pool.rb +0 -85
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/show_exceptions.rb +0 -390
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/show_status.rb +0 -113
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/static.rb +0 -187
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/tempfile_reaper.rb +0 -22
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/urlmap.rb +0 -97
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/utils.rb +0 -616
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack/version.rb +0 -29
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/lib/rack.rb +0 -141
- data/vendor/bundle/ruby/3.0.0/gems/rack-2.2.4/rack.gemspec +0 -46
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/History.rdoc +0 -2403
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/MIT-LICENSE +0 -21
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/README.rdoc +0 -155
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/command_line_usage.rdoc +0 -158
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/Rakefile1 +0 -38
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/Rakefile2 +0 -35
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/a.c +0 -6
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/b.c +0 -6
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/example/main.c +0 -11
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/glossary.rdoc +0 -42
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/jamis.rb +0 -592
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/proto_rake.rdoc +0 -127
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rake.1 +0 -156
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rakefile.rdoc +0 -622
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/doc/rational.rdoc +0 -151
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/exe/rake +0 -27
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb +0 -831
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/backtrace.rb +0 -24
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/clean.rb +0 -78
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/cloneable.rb +0 -17
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/cpu_counter.rb +0 -107
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/default_loader.rb +0 -15
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/dsl_definition.rb +0 -195
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/early_time.rb +0 -22
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/ext/core.rb +0 -26
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/ext/string.rb +0 -176
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_creation_task.rb +0 -25
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_list.rb +0 -435
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_task.rb +0 -54
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_utils.rb +0 -134
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/file_utils_ext.rb +0 -134
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/invocation_chain.rb +0 -57
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/invocation_exception_mixin.rb +0 -17
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/late_time.rb +0 -18
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/linked_list.rb +0 -112
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/loaders/makefile.rb +0 -54
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/multi_task.rb +0 -14
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/name_space.rb +0 -38
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/packagetask.rb +0 -222
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/phony.rb +0 -16
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/private_reader.rb +0 -21
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/promise.rb +0 -100
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/pseudo_status.rb +0 -30
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_module.rb +0 -67
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_test_loader.rb +0 -27
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rule_recursion_overflow_error.rb +0 -20
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/scope.rb +0 -43
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb +0 -434
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_argument_error.rb +0 -8
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_arguments.rb +0 -109
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_manager.rb +0 -331
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/tasklib.rb +0 -12
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/testtask.rb +0 -189
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/thread_history_display.rb +0 -49
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/thread_pool.rb +0 -163
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/trace_output.rb +0 -23
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/version.rb +0 -10
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/win32.rb +0 -51
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake.rb +0 -71
- data/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/rake.gemspec +0 -100
- data/vendor/bundle/ruby/3.0.0/specifications/rack-2.2.4.gemspec +0 -41
- data/vendor/bundle/ruby/3.0.0/specifications/rake-13.0.6.gemspec +0 -26
@@ -1,616 +0,0 @@
|
|
1
|
-
# -*- encoding: binary -*-
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require 'uri'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'set'
|
7
|
-
require 'tempfile'
|
8
|
-
require 'time'
|
9
|
-
|
10
|
-
require_relative 'query_parser'
|
11
|
-
|
12
|
-
module Rack
|
13
|
-
# Rack::Utils contains a grab-bag of useful methods for writing web
|
14
|
-
# applications adopted from all kinds of Ruby libraries.
|
15
|
-
|
16
|
-
module Utils
|
17
|
-
(require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
|
18
|
-
|
19
|
-
ParameterTypeError = QueryParser::ParameterTypeError
|
20
|
-
InvalidParameterError = QueryParser::InvalidParameterError
|
21
|
-
DEFAULT_SEP = QueryParser::DEFAULT_SEP
|
22
|
-
COMMON_SEP = QueryParser::COMMON_SEP
|
23
|
-
KeySpaceConstrainedParams = QueryParser::Params
|
24
|
-
|
25
|
-
RFC2822_DAY_NAME = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
26
|
-
RFC2822_MONTH_NAME = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
|
27
|
-
|
28
|
-
class << self
|
29
|
-
attr_accessor :default_query_parser
|
30
|
-
end
|
31
|
-
# The default number of bytes to allow parameter keys to take up.
|
32
|
-
# This helps prevent a rogue client from flooding a Request.
|
33
|
-
self.default_query_parser = QueryParser.make_default(65536, 100)
|
34
|
-
|
35
|
-
module_function
|
36
|
-
|
37
|
-
# URI escapes. (CGI style space to +)
|
38
|
-
def escape(s)
|
39
|
-
URI.encode_www_form_component(s)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Like URI escaping, but with %20 instead of +. Strictly speaking this is
|
43
|
-
# true URI escaping.
|
44
|
-
def escape_path(s)
|
45
|
-
::URI::DEFAULT_PARSER.escape s
|
46
|
-
end
|
47
|
-
|
48
|
-
# Unescapes the **path** component of a URI. See Rack::Utils.unescape for
|
49
|
-
# unescaping query parameters or form components.
|
50
|
-
def unescape_path(s)
|
51
|
-
::URI::DEFAULT_PARSER.unescape s
|
52
|
-
end
|
53
|
-
|
54
|
-
# Unescapes a URI escaped string with +encoding+. +encoding+ will be the
|
55
|
-
# target encoding of the string returned, and it defaults to UTF-8
|
56
|
-
def unescape(s, encoding = Encoding::UTF_8)
|
57
|
-
URI.decode_www_form_component(s, encoding)
|
58
|
-
end
|
59
|
-
|
60
|
-
class << self
|
61
|
-
attr_accessor :multipart_part_limit
|
62
|
-
end
|
63
|
-
|
64
|
-
# The maximum number of parts a request can contain. Accepting too many part
|
65
|
-
# can lead to the server running out of file handles.
|
66
|
-
# Set to `0` for no limit.
|
67
|
-
self.multipart_part_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || 128).to_i
|
68
|
-
|
69
|
-
def self.param_depth_limit
|
70
|
-
default_query_parser.param_depth_limit
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.param_depth_limit=(v)
|
74
|
-
self.default_query_parser = self.default_query_parser.new_depth_limit(v)
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.key_space_limit
|
78
|
-
default_query_parser.key_space_limit
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.key_space_limit=(v)
|
82
|
-
self.default_query_parser = self.default_query_parser.new_space_limit(v)
|
83
|
-
end
|
84
|
-
|
85
|
-
if defined?(Process::CLOCK_MONOTONIC)
|
86
|
-
def clock_time
|
87
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
88
|
-
end
|
89
|
-
else
|
90
|
-
# :nocov:
|
91
|
-
def clock_time
|
92
|
-
Time.now.to_f
|
93
|
-
end
|
94
|
-
# :nocov:
|
95
|
-
end
|
96
|
-
|
97
|
-
def parse_query(qs, d = nil, &unescaper)
|
98
|
-
Rack::Utils.default_query_parser.parse_query(qs, d, &unescaper)
|
99
|
-
end
|
100
|
-
|
101
|
-
def parse_nested_query(qs, d = nil)
|
102
|
-
Rack::Utils.default_query_parser.parse_nested_query(qs, d)
|
103
|
-
end
|
104
|
-
|
105
|
-
def build_query(params)
|
106
|
-
params.map { |k, v|
|
107
|
-
if v.class == Array
|
108
|
-
build_query(v.map { |x| [k, x] })
|
109
|
-
else
|
110
|
-
v.nil? ? escape(k) : "#{escape(k)}=#{escape(v)}"
|
111
|
-
end
|
112
|
-
}.join("&")
|
113
|
-
end
|
114
|
-
|
115
|
-
def build_nested_query(value, prefix = nil)
|
116
|
-
case value
|
117
|
-
when Array
|
118
|
-
value.map { |v|
|
119
|
-
build_nested_query(v, "#{prefix}[]")
|
120
|
-
}.join("&")
|
121
|
-
when Hash
|
122
|
-
value.map { |k, v|
|
123
|
-
build_nested_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
|
124
|
-
}.delete_if(&:empty?).join('&')
|
125
|
-
when nil
|
126
|
-
prefix
|
127
|
-
else
|
128
|
-
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
129
|
-
"#{prefix}=#{escape(value)}"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def q_values(q_value_header)
|
134
|
-
q_value_header.to_s.split(/\s*,\s*/).map do |part|
|
135
|
-
value, parameters = part.split(/\s*;\s*/, 2)
|
136
|
-
quality = 1.0
|
137
|
-
if parameters && (md = /\Aq=([\d.]+)/.match(parameters))
|
138
|
-
quality = md[1].to_f
|
139
|
-
end
|
140
|
-
[value, quality]
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Return best accept value to use, based on the algorithm
|
145
|
-
# in RFC 2616 Section 14. If there are multiple best
|
146
|
-
# matches (same specificity and quality), the value returned
|
147
|
-
# is arbitrary.
|
148
|
-
def best_q_match(q_value_header, available_mimes)
|
149
|
-
values = q_values(q_value_header)
|
150
|
-
|
151
|
-
matches = values.map do |req_mime, quality|
|
152
|
-
match = available_mimes.find { |am| Rack::Mime.match?(am, req_mime) }
|
153
|
-
next unless match
|
154
|
-
[match, quality]
|
155
|
-
end.compact.sort_by do |match, quality|
|
156
|
-
(match.split('/', 2).count('*') * -10) + quality
|
157
|
-
end.last
|
158
|
-
matches && matches.first
|
159
|
-
end
|
160
|
-
|
161
|
-
ESCAPE_HTML = {
|
162
|
-
"&" => "&",
|
163
|
-
"<" => "<",
|
164
|
-
">" => ">",
|
165
|
-
"'" => "'",
|
166
|
-
'"' => """,
|
167
|
-
"/" => "/"
|
168
|
-
}
|
169
|
-
|
170
|
-
ESCAPE_HTML_PATTERN = Regexp.union(*ESCAPE_HTML.keys)
|
171
|
-
|
172
|
-
# Escape ampersands, brackets and quotes to their HTML/XML entities.
|
173
|
-
def escape_html(string)
|
174
|
-
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
175
|
-
end
|
176
|
-
|
177
|
-
def select_best_encoding(available_encodings, accept_encoding)
|
178
|
-
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
179
|
-
|
180
|
-
expanded_accept_encoding = []
|
181
|
-
|
182
|
-
accept_encoding.each do |m, q|
|
183
|
-
preference = available_encodings.index(m) || available_encodings.size
|
184
|
-
|
185
|
-
if m == "*"
|
186
|
-
(available_encodings - accept_encoding.map(&:first)).each do |m2|
|
187
|
-
expanded_accept_encoding << [m2, q, preference]
|
188
|
-
end
|
189
|
-
else
|
190
|
-
expanded_accept_encoding << [m, q, preference]
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
encoding_candidates = expanded_accept_encoding
|
195
|
-
.sort_by { |_, q, p| [-q, p] }
|
196
|
-
.map!(&:first)
|
197
|
-
|
198
|
-
unless encoding_candidates.include?("identity")
|
199
|
-
encoding_candidates.push("identity")
|
200
|
-
end
|
201
|
-
|
202
|
-
expanded_accept_encoding.each do |m, q|
|
203
|
-
encoding_candidates.delete(m) if q == 0.0
|
204
|
-
end
|
205
|
-
|
206
|
-
(encoding_candidates & available_encodings)[0]
|
207
|
-
end
|
208
|
-
|
209
|
-
def parse_cookies(env)
|
210
|
-
parse_cookies_header env[HTTP_COOKIE]
|
211
|
-
end
|
212
|
-
|
213
|
-
def parse_cookies_header(header)
|
214
|
-
# According to RFC 6265:
|
215
|
-
# The syntax for cookie headers only supports semicolons
|
216
|
-
# User Agent -> Server ==
|
217
|
-
# Cookie: SID=31d4d96e407aad42; lang=en-US
|
218
|
-
return {} unless header
|
219
|
-
header.split(/[;] */n).each_with_object({}) do |cookie, cookies|
|
220
|
-
next if cookie.empty?
|
221
|
-
key, value = cookie.split('=', 2)
|
222
|
-
cookies[key] = (unescape(value) rescue value) unless cookies.key?(key)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def add_cookie_to_header(header, key, value)
|
227
|
-
case value
|
228
|
-
when Hash
|
229
|
-
domain = "; domain=#{value[:domain]}" if value[:domain]
|
230
|
-
path = "; path=#{value[:path]}" if value[:path]
|
231
|
-
max_age = "; max-age=#{value[:max_age]}" if value[:max_age]
|
232
|
-
expires = "; expires=#{value[:expires].httpdate}" if value[:expires]
|
233
|
-
secure = "; secure" if value[:secure]
|
234
|
-
httponly = "; HttpOnly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only])
|
235
|
-
same_site =
|
236
|
-
case value[:same_site]
|
237
|
-
when false, nil
|
238
|
-
nil
|
239
|
-
when :none, 'None', :None
|
240
|
-
'; SameSite=None'
|
241
|
-
when :lax, 'Lax', :Lax
|
242
|
-
'; SameSite=Lax'
|
243
|
-
when true, :strict, 'Strict', :Strict
|
244
|
-
'; SameSite=Strict'
|
245
|
-
else
|
246
|
-
raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
|
247
|
-
end
|
248
|
-
value = value[:value]
|
249
|
-
end
|
250
|
-
value = [value] unless Array === value
|
251
|
-
|
252
|
-
cookie = "#{escape(key)}=#{value.map { |v| escape v }.join('&')}#{domain}" \
|
253
|
-
"#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
|
254
|
-
|
255
|
-
case header
|
256
|
-
when nil, ''
|
257
|
-
cookie
|
258
|
-
when String
|
259
|
-
[header, cookie].join("\n")
|
260
|
-
when Array
|
261
|
-
(header + [cookie]).join("\n")
|
262
|
-
else
|
263
|
-
raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}"
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
def set_cookie_header!(header, key, value)
|
268
|
-
header[SET_COOKIE] = add_cookie_to_header(header[SET_COOKIE], key, value)
|
269
|
-
nil
|
270
|
-
end
|
271
|
-
|
272
|
-
def make_delete_cookie_header(header, key, value)
|
273
|
-
case header
|
274
|
-
when nil, ''
|
275
|
-
cookies = []
|
276
|
-
when String
|
277
|
-
cookies = header.split("\n")
|
278
|
-
when Array
|
279
|
-
cookies = header
|
280
|
-
end
|
281
|
-
|
282
|
-
key = escape(key)
|
283
|
-
domain = value[:domain]
|
284
|
-
path = value[:path]
|
285
|
-
regexp = if domain
|
286
|
-
if path
|
287
|
-
/\A#{key}=.*(?:domain=#{domain}(?:;|$).*path=#{path}(?:;|$)|path=#{path}(?:;|$).*domain=#{domain}(?:;|$))/
|
288
|
-
else
|
289
|
-
/\A#{key}=.*domain=#{domain}(?:;|$)/
|
290
|
-
end
|
291
|
-
elsif path
|
292
|
-
/\A#{key}=.*path=#{path}(?:;|$)/
|
293
|
-
else
|
294
|
-
/\A#{key}=/
|
295
|
-
end
|
296
|
-
|
297
|
-
cookies.reject! { |cookie| regexp.match? cookie }
|
298
|
-
|
299
|
-
cookies.join("\n")
|
300
|
-
end
|
301
|
-
|
302
|
-
def delete_cookie_header!(header, key, value = {})
|
303
|
-
header[SET_COOKIE] = add_remove_cookie_to_header(header[SET_COOKIE], key, value)
|
304
|
-
nil
|
305
|
-
end
|
306
|
-
|
307
|
-
# Adds a cookie that will *remove* a cookie from the client. Hence the
|
308
|
-
# strange method name.
|
309
|
-
def add_remove_cookie_to_header(header, key, value = {})
|
310
|
-
new_header = make_delete_cookie_header(header, key, value)
|
311
|
-
|
312
|
-
add_cookie_to_header(new_header, key,
|
313
|
-
{ value: '', path: nil, domain: nil,
|
314
|
-
max_age: '0',
|
315
|
-
expires: Time.at(0) }.merge(value))
|
316
|
-
|
317
|
-
end
|
318
|
-
|
319
|
-
def rfc2822(time)
|
320
|
-
time.rfc2822
|
321
|
-
end
|
322
|
-
|
323
|
-
# Modified version of stdlib time.rb Time#rfc2822 to use '%d-%b-%Y' instead
|
324
|
-
# of '% %b %Y'.
|
325
|
-
# It assumes that the time is in GMT to comply to the RFC 2109.
|
326
|
-
#
|
327
|
-
# NOTE: I'm not sure the RFC says it requires GMT, but is ambiguous enough
|
328
|
-
# that I'm certain someone implemented only that option.
|
329
|
-
# Do not use %a and %b from Time.strptime, it would use localized names for
|
330
|
-
# weekday and month.
|
331
|
-
#
|
332
|
-
def rfc2109(time)
|
333
|
-
wday = RFC2822_DAY_NAME[time.wday]
|
334
|
-
mon = RFC2822_MONTH_NAME[time.mon - 1]
|
335
|
-
time.strftime("#{wday}, %d-#{mon}-%Y %H:%M:%S GMT")
|
336
|
-
end
|
337
|
-
|
338
|
-
# Parses the "Range:" header, if present, into an array of Range objects.
|
339
|
-
# Returns nil if the header is missing or syntactically invalid.
|
340
|
-
# Returns an empty array if none of the ranges are satisfiable.
|
341
|
-
def byte_ranges(env, size)
|
342
|
-
warn "`byte_ranges` is deprecated, please use `get_byte_ranges`" if $VERBOSE
|
343
|
-
get_byte_ranges env['HTTP_RANGE'], size
|
344
|
-
end
|
345
|
-
|
346
|
-
def get_byte_ranges(http_range, size)
|
347
|
-
# See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35>
|
348
|
-
return nil unless http_range && http_range =~ /bytes=([^;]+)/
|
349
|
-
ranges = []
|
350
|
-
$1.split(/,\s*/).each do |range_spec|
|
351
|
-
return nil unless range_spec =~ /(\d*)-(\d*)/
|
352
|
-
r0, r1 = $1, $2
|
353
|
-
if r0.empty?
|
354
|
-
return nil if r1.empty?
|
355
|
-
# suffix-byte-range-spec, represents trailing suffix of file
|
356
|
-
r0 = size - r1.to_i
|
357
|
-
r0 = 0 if r0 < 0
|
358
|
-
r1 = size - 1
|
359
|
-
else
|
360
|
-
r0 = r0.to_i
|
361
|
-
if r1.empty?
|
362
|
-
r1 = size - 1
|
363
|
-
else
|
364
|
-
r1 = r1.to_i
|
365
|
-
return nil if r1 < r0 # backwards range is syntactically invalid
|
366
|
-
r1 = size - 1 if r1 >= size
|
367
|
-
end
|
368
|
-
end
|
369
|
-
ranges << (r0..r1) if r0 <= r1
|
370
|
-
end
|
371
|
-
ranges
|
372
|
-
end
|
373
|
-
|
374
|
-
# Constant time string comparison.
|
375
|
-
#
|
376
|
-
# NOTE: the values compared should be of fixed length, such as strings
|
377
|
-
# that have already been processed by HMAC. This should not be used
|
378
|
-
# on variable length plaintext strings because it could leak length info
|
379
|
-
# via timing attacks.
|
380
|
-
def secure_compare(a, b)
|
381
|
-
return false unless a.bytesize == b.bytesize
|
382
|
-
|
383
|
-
l = a.unpack("C*")
|
384
|
-
|
385
|
-
r, i = 0, -1
|
386
|
-
b.each_byte { |v| r |= v ^ l[i += 1] }
|
387
|
-
r == 0
|
388
|
-
end
|
389
|
-
|
390
|
-
# Context allows the use of a compatible middleware at different points
|
391
|
-
# in a request handling stack. A compatible middleware must define
|
392
|
-
# #context which should take the arguments env and app. The first of which
|
393
|
-
# would be the request environment. The second of which would be the rack
|
394
|
-
# application that the request would be forwarded to.
|
395
|
-
class Context
|
396
|
-
attr_reader :for, :app
|
397
|
-
|
398
|
-
def initialize(app_f, app_r)
|
399
|
-
raise 'running context does not respond to #context' unless app_f.respond_to? :context
|
400
|
-
@for, @app = app_f, app_r
|
401
|
-
end
|
402
|
-
|
403
|
-
def call(env)
|
404
|
-
@for.context(env, @app)
|
405
|
-
end
|
406
|
-
|
407
|
-
def recontext(app)
|
408
|
-
self.class.new(@for, app)
|
409
|
-
end
|
410
|
-
|
411
|
-
def context(env, app = @app)
|
412
|
-
recontext(app).call(env)
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
# A case-insensitive Hash that preserves the original case of a
|
417
|
-
# header when set.
|
418
|
-
#
|
419
|
-
# @api private
|
420
|
-
class HeaderHash < Hash # :nodoc:
|
421
|
-
def self.[](headers)
|
422
|
-
if headers.is_a?(HeaderHash) && !headers.frozen?
|
423
|
-
return headers
|
424
|
-
else
|
425
|
-
return self.new(headers)
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
def initialize(hash = {})
|
430
|
-
super()
|
431
|
-
@names = {}
|
432
|
-
hash.each { |k, v| self[k] = v }
|
433
|
-
end
|
434
|
-
|
435
|
-
# on dup/clone, we need to duplicate @names hash
|
436
|
-
def initialize_copy(other)
|
437
|
-
super
|
438
|
-
@names = other.names.dup
|
439
|
-
end
|
440
|
-
|
441
|
-
# on clear, we need to clear @names hash
|
442
|
-
def clear
|
443
|
-
super
|
444
|
-
@names.clear
|
445
|
-
end
|
446
|
-
|
447
|
-
def each
|
448
|
-
super do |k, v|
|
449
|
-
yield(k, v.respond_to?(:to_ary) ? v.to_ary.join("\n") : v)
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
def to_hash
|
454
|
-
hash = {}
|
455
|
-
each { |k, v| hash[k] = v }
|
456
|
-
hash
|
457
|
-
end
|
458
|
-
|
459
|
-
def [](k)
|
460
|
-
super(k) || super(@names[k.downcase])
|
461
|
-
end
|
462
|
-
|
463
|
-
def []=(k, v)
|
464
|
-
canonical = k.downcase.freeze
|
465
|
-
delete k if @names[canonical] && @names[canonical] != k # .delete is expensive, don't invoke it unless necessary
|
466
|
-
@names[canonical] = k
|
467
|
-
super k, v
|
468
|
-
end
|
469
|
-
|
470
|
-
def delete(k)
|
471
|
-
canonical = k.downcase
|
472
|
-
result = super @names.delete(canonical)
|
473
|
-
result
|
474
|
-
end
|
475
|
-
|
476
|
-
def include?(k)
|
477
|
-
super || @names.include?(k.downcase)
|
478
|
-
end
|
479
|
-
|
480
|
-
alias_method :has_key?, :include?
|
481
|
-
alias_method :member?, :include?
|
482
|
-
alias_method :key?, :include?
|
483
|
-
|
484
|
-
def merge!(other)
|
485
|
-
other.each { |k, v| self[k] = v }
|
486
|
-
self
|
487
|
-
end
|
488
|
-
|
489
|
-
def merge(other)
|
490
|
-
hash = dup
|
491
|
-
hash.merge! other
|
492
|
-
end
|
493
|
-
|
494
|
-
def replace(other)
|
495
|
-
clear
|
496
|
-
other.each { |k, v| self[k] = v }
|
497
|
-
self
|
498
|
-
end
|
499
|
-
|
500
|
-
protected
|
501
|
-
def names
|
502
|
-
@names
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
|
-
# Every standard HTTP code mapped to the appropriate message.
|
507
|
-
# Generated with:
|
508
|
-
# curl -s https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv | \
|
509
|
-
# ruby -ne 'm = /^(\d{3}),(?!Unassigned|\(Unused\))([^,]+)/.match($_) and \
|
510
|
-
# puts "#{m[1]} => \x27#{m[2].strip}\x27,"'
|
511
|
-
HTTP_STATUS_CODES = {
|
512
|
-
100 => 'Continue',
|
513
|
-
101 => 'Switching Protocols',
|
514
|
-
102 => 'Processing',
|
515
|
-
103 => 'Early Hints',
|
516
|
-
200 => 'OK',
|
517
|
-
201 => 'Created',
|
518
|
-
202 => 'Accepted',
|
519
|
-
203 => 'Non-Authoritative Information',
|
520
|
-
204 => 'No Content',
|
521
|
-
205 => 'Reset Content',
|
522
|
-
206 => 'Partial Content',
|
523
|
-
207 => 'Multi-Status',
|
524
|
-
208 => 'Already Reported',
|
525
|
-
226 => 'IM Used',
|
526
|
-
300 => 'Multiple Choices',
|
527
|
-
301 => 'Moved Permanently',
|
528
|
-
302 => 'Found',
|
529
|
-
303 => 'See Other',
|
530
|
-
304 => 'Not Modified',
|
531
|
-
305 => 'Use Proxy',
|
532
|
-
306 => '(Unused)',
|
533
|
-
307 => 'Temporary Redirect',
|
534
|
-
308 => 'Permanent Redirect',
|
535
|
-
400 => 'Bad Request',
|
536
|
-
401 => 'Unauthorized',
|
537
|
-
402 => 'Payment Required',
|
538
|
-
403 => 'Forbidden',
|
539
|
-
404 => 'Not Found',
|
540
|
-
405 => 'Method Not Allowed',
|
541
|
-
406 => 'Not Acceptable',
|
542
|
-
407 => 'Proxy Authentication Required',
|
543
|
-
408 => 'Request Timeout',
|
544
|
-
409 => 'Conflict',
|
545
|
-
410 => 'Gone',
|
546
|
-
411 => 'Length Required',
|
547
|
-
412 => 'Precondition Failed',
|
548
|
-
413 => 'Payload Too Large',
|
549
|
-
414 => 'URI Too Long',
|
550
|
-
415 => 'Unsupported Media Type',
|
551
|
-
416 => 'Range Not Satisfiable',
|
552
|
-
417 => 'Expectation Failed',
|
553
|
-
421 => 'Misdirected Request',
|
554
|
-
422 => 'Unprocessable Entity',
|
555
|
-
423 => 'Locked',
|
556
|
-
424 => 'Failed Dependency',
|
557
|
-
425 => 'Too Early',
|
558
|
-
426 => 'Upgrade Required',
|
559
|
-
428 => 'Precondition Required',
|
560
|
-
429 => 'Too Many Requests',
|
561
|
-
431 => 'Request Header Fields Too Large',
|
562
|
-
451 => 'Unavailable for Legal Reasons',
|
563
|
-
500 => 'Internal Server Error',
|
564
|
-
501 => 'Not Implemented',
|
565
|
-
502 => 'Bad Gateway',
|
566
|
-
503 => 'Service Unavailable',
|
567
|
-
504 => 'Gateway Timeout',
|
568
|
-
505 => 'HTTP Version Not Supported',
|
569
|
-
506 => 'Variant Also Negotiates',
|
570
|
-
507 => 'Insufficient Storage',
|
571
|
-
508 => 'Loop Detected',
|
572
|
-
509 => 'Bandwidth Limit Exceeded',
|
573
|
-
510 => 'Not Extended',
|
574
|
-
511 => 'Network Authentication Required'
|
575
|
-
}
|
576
|
-
|
577
|
-
# Responses with HTTP status codes that should not have an entity body
|
578
|
-
STATUS_WITH_NO_ENTITY_BODY = Hash[((100..199).to_a << 204 << 304).product([true])]
|
579
|
-
|
580
|
-
SYMBOL_TO_STATUS_CODE = Hash[*HTTP_STATUS_CODES.map { |code, message|
|
581
|
-
[message.downcase.gsub(/\s|-|'/, '_').to_sym, code]
|
582
|
-
}.flatten]
|
583
|
-
|
584
|
-
def status_code(status)
|
585
|
-
if status.is_a?(Symbol)
|
586
|
-
SYMBOL_TO_STATUS_CODE.fetch(status) { raise ArgumentError, "Unrecognized status code #{status.inspect}" }
|
587
|
-
else
|
588
|
-
status.to_i
|
589
|
-
end
|
590
|
-
end
|
591
|
-
|
592
|
-
PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact)
|
593
|
-
|
594
|
-
def clean_path_info(path_info)
|
595
|
-
parts = path_info.split PATH_SEPS
|
596
|
-
|
597
|
-
clean = []
|
598
|
-
|
599
|
-
parts.each do |part|
|
600
|
-
next if part.empty? || part == '.'
|
601
|
-
part == '..' ? clean.pop : clean << part
|
602
|
-
end
|
603
|
-
|
604
|
-
clean_path = clean.join(::File::SEPARATOR)
|
605
|
-
clean_path.prepend("/") if parts.empty? || parts.first.empty?
|
606
|
-
clean_path
|
607
|
-
end
|
608
|
-
|
609
|
-
NULL_BYTE = "\0"
|
610
|
-
|
611
|
-
def valid_path?(path)
|
612
|
-
path.valid_encoding? && !path.include?(NULL_BYTE)
|
613
|
-
end
|
614
|
-
|
615
|
-
end
|
616
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (C) 2007-2019 Leah Neukirchen <http://leahneukirchen.org/infopage.html>
|
4
|
-
#
|
5
|
-
# Rack is freely distributable under the terms of an MIT-style license.
|
6
|
-
# See MIT-LICENSE or https://opensource.org/licenses/MIT.
|
7
|
-
|
8
|
-
# The Rack main module, serving as a namespace for all core Rack
|
9
|
-
# modules and classes.
|
10
|
-
#
|
11
|
-
# All modules meant for use in your application are <tt>autoload</tt>ed here,
|
12
|
-
# so it should be enough just to <tt>require 'rack'</tt> in your code.
|
13
|
-
|
14
|
-
module Rack
|
15
|
-
# The Rack protocol version number implemented.
|
16
|
-
VERSION = [1, 3]
|
17
|
-
|
18
|
-
# Return the Rack protocol version as a dotted string.
|
19
|
-
def self.version
|
20
|
-
VERSION.join(".")
|
21
|
-
end
|
22
|
-
|
23
|
-
RELEASE = "2.2.4"
|
24
|
-
|
25
|
-
# Return the Rack release as a dotted string.
|
26
|
-
def self.release
|
27
|
-
RELEASE
|
28
|
-
end
|
29
|
-
end
|