homura-runtime 0.3.2 → 0.3.4

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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/exe/compile-assets +2 -2
  4. data/exe/compile-erb +5 -7
  5. data/lib/homura/runtime/build_support.rb +19 -2
  6. data/lib/homura/runtime/version.rb +1 -1
  7. data/vendor/rack/auth/abstract/handler.rb +41 -0
  8. data/vendor/rack/auth/abstract/request.rb +51 -0
  9. data/vendor/rack/auth/basic.rb +58 -0
  10. data/vendor/rack/bad_request.rb +8 -0
  11. data/vendor/rack/body_proxy.rb +63 -0
  12. data/vendor/rack/builder.rb +315 -0
  13. data/vendor/rack/cascade.rb +67 -0
  14. data/vendor/rack/common_logger.rb +94 -0
  15. data/vendor/rack/conditional_get.rb +87 -0
  16. data/vendor/rack/config.rb +22 -0
  17. data/vendor/rack/constants.rb +68 -0
  18. data/vendor/rack/content_length.rb +34 -0
  19. data/vendor/rack/content_type.rb +33 -0
  20. data/vendor/rack/deflater.rb +159 -0
  21. data/vendor/rack/directory.rb +210 -0
  22. data/vendor/rack/etag.rb +71 -0
  23. data/vendor/rack/events.rb +172 -0
  24. data/vendor/rack/files.rb +224 -0
  25. data/vendor/rack/head.rb +25 -0
  26. data/vendor/rack/headers.rb +238 -0
  27. data/vendor/rack/lint.rb +1000 -0
  28. data/vendor/rack/lock.rb +29 -0
  29. data/vendor/rack/media_type.rb +42 -0
  30. data/vendor/rack/method_override.rb +56 -0
  31. data/vendor/rack/mime.rb +694 -0
  32. data/vendor/rack/mock.rb +3 -0
  33. data/vendor/rack/mock_request.rb +161 -0
  34. data/vendor/rack/mock_response.rb +147 -0
  35. data/vendor/rack/multipart/generator.rb +99 -0
  36. data/vendor/rack/multipart/parser.rb +586 -0
  37. data/vendor/rack/multipart/uploaded_file.rb +82 -0
  38. data/vendor/rack/multipart.rb +77 -0
  39. data/vendor/rack/null_logger.rb +48 -0
  40. data/vendor/rack/protection/authenticity_token.rb +256 -0
  41. data/vendor/rack/protection/base.rb +140 -0
  42. data/vendor/rack/protection/content_security_policy.rb +80 -0
  43. data/vendor/rack/protection/cookie_tossing.rb +77 -0
  44. data/vendor/rack/protection/escaped_params.rb +93 -0
  45. data/vendor/rack/protection/form_token.rb +25 -0
  46. data/vendor/rack/protection/frame_options.rb +39 -0
  47. data/vendor/rack/protection/http_origin.rb +43 -0
  48. data/vendor/rack/protection/ip_spoofing.rb +27 -0
  49. data/vendor/rack/protection/json_csrf.rb +60 -0
  50. data/vendor/rack/protection/path_traversal.rb +45 -0
  51. data/vendor/rack/protection/referrer_policy.rb +27 -0
  52. data/vendor/rack/protection/remote_referrer.rb +22 -0
  53. data/vendor/rack/protection/remote_token.rb +24 -0
  54. data/vendor/rack/protection/session_hijacking.rb +37 -0
  55. data/vendor/rack/protection/strict_transport.rb +41 -0
  56. data/vendor/rack/protection/version.rb +7 -0
  57. data/vendor/rack/protection/xss_header.rb +27 -0
  58. data/vendor/rack/protection.rb +58 -0
  59. data/vendor/rack/query_parser.rb +261 -0
  60. data/vendor/rack/recursive.rb +66 -0
  61. data/vendor/rack/reloader.rb +112 -0
  62. data/vendor/rack/request.rb +818 -0
  63. data/vendor/rack/response.rb +403 -0
  64. data/vendor/rack/rewindable_input.rb +116 -0
  65. data/vendor/rack/runtime.rb +35 -0
  66. data/vendor/rack/sendfile.rb +197 -0
  67. data/vendor/rack/session/abstract/id.rb +533 -0
  68. data/vendor/rack/session/constants.rb +13 -0
  69. data/vendor/rack/session/cookie.rb +292 -0
  70. data/vendor/rack/session/encryptor.rb +415 -0
  71. data/vendor/rack/session/pool.rb +76 -0
  72. data/vendor/rack/session/version.rb +10 -0
  73. data/vendor/rack/session.rb +12 -0
  74. data/vendor/rack/show_exceptions.rb +433 -0
  75. data/vendor/rack/show_status.rb +121 -0
  76. data/vendor/rack/static.rb +188 -0
  77. data/vendor/rack/tempfile_reaper.rb +44 -0
  78. data/vendor/rack/urlmap.rb +99 -0
  79. data/vendor/rack/utils.rb +631 -0
  80. data/vendor/rack/version.rb +17 -0
  81. data/vendor/rack.rb +66 -0
  82. metadata +76 -1
@@ -0,0 +1,261 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bad_request'
4
+ require 'uri'
5
+
6
+ module Rack
7
+ class QueryParser
8
+ DEFAULT_SEP = /& */n
9
+ COMMON_SEP = { ";" => /; */n, ";," => /[;,] */n, "&" => /& */n }
10
+
11
+ # ParameterTypeError is the error that is raised when incoming structural
12
+ # parameters (parsed by parse_nested_query) contain conflicting types.
13
+ class ParameterTypeError < TypeError
14
+ include BadRequest
15
+ end
16
+
17
+ # InvalidParameterError is the error that is raised when incoming structural
18
+ # parameters (parsed by parse_nested_query) contain invalid format or byte
19
+ # sequence.
20
+ class InvalidParameterError < ArgumentError
21
+ include BadRequest
22
+ end
23
+
24
+ # QueryLimitError is for errors raised when the query provided exceeds one
25
+ # of the query parser limits.
26
+ class QueryLimitError < RangeError
27
+ include BadRequest
28
+ end
29
+
30
+ # ParamsTooDeepError is the old name for the error that is raised when params
31
+ # are recursively nested over the specified limit. Make it the same as
32
+ # as QueryLimitError, so that code that rescues ParamsTooDeepError error
33
+ # to handle bad query strings also now handles other limits.
34
+ ParamsTooDeepError = QueryLimitError
35
+
36
+ def self.make_default(param_depth_limit, **options)
37
+ new(Params, param_depth_limit, **options)
38
+ end
39
+
40
+ attr_reader :param_depth_limit
41
+
42
+ env_int = lambda do |key, val|
43
+ if str_val = ENV[key]
44
+ begin
45
+ val = Integer(str_val, 10)
46
+ rescue ArgumentError
47
+ raise ArgumentError, "non-integer value provided for environment variable #{key}"
48
+ end
49
+ end
50
+
51
+ val
52
+ end
53
+
54
+ BYTESIZE_LIMIT = env_int.call("RACK_QUERY_PARSER_BYTESIZE_LIMIT", 4194304)
55
+ private_constant :BYTESIZE_LIMIT
56
+
57
+ PARAMS_LIMIT = env_int.call("RACK_QUERY_PARSER_PARAMS_LIMIT", 4096)
58
+ private_constant :PARAMS_LIMIT
59
+
60
+ attr_reader :bytesize_limit
61
+
62
+ def initialize(params_class, param_depth_limit, bytesize_limit: BYTESIZE_LIMIT, params_limit: PARAMS_LIMIT)
63
+ @params_class = params_class
64
+ @param_depth_limit = param_depth_limit
65
+ @bytesize_limit = bytesize_limit
66
+ @params_limit = params_limit
67
+ end
68
+
69
+ # Stolen from Mongrel, with some small modifications:
70
+ # Parses a query string by breaking it up at the '&'. You can also use this
71
+ # to parse cookies by changing the characters used in the second parameter
72
+ # (which defaults to '&').
73
+ def parse_query(qs, separator = nil, &unescaper)
74
+ params = make_params
75
+
76
+ each_query_pair(qs, separator, unescaper) do |k, v|
77
+ if cur = params[k]
78
+ if cur.class == Array
79
+ params[k] << v
80
+ else
81
+ params[k] = [cur, v]
82
+ end
83
+ else
84
+ params[k] = v
85
+ end
86
+ end
87
+
88
+ return params.to_h
89
+ end
90
+
91
+ # Parses a query string by breaking it up at the '&', returning all key-value
92
+ # pairs as an array of [key, value] arrays. Unlike parse_query, this preserves
93
+ # all duplicate keys rather than collapsing them.
94
+ def parse_query_pairs(qs, separator = nil)
95
+ pairs = []
96
+
97
+ each_query_pair(qs, separator) do |k, v|
98
+ pairs << [k, v]
99
+ end
100
+
101
+ pairs
102
+ end
103
+
104
+ # parse_nested_query expands a query string into structural types. Supported
105
+ # types are Arrays, Hashes and basic value types. It is possible to supply
106
+ # query strings with parameters of conflicting types, in this case a
107
+ # ParameterTypeError is raised. Users are encouraged to return a 400 in this
108
+ # case.
109
+ def parse_nested_query(qs, separator = nil)
110
+ params = make_params
111
+
112
+ each_query_pair(qs, separator) do |k, v|
113
+ _normalize_params(params, k, v, 0)
114
+ end
115
+
116
+ return params.to_h
117
+ end
118
+
119
+ # normalize_params recursively expands parameters into structural types. If
120
+ # the structural types represented by two different parameter names are in
121
+ # conflict, a ParameterTypeError is raised. The depth argument is deprecated
122
+ # and should no longer be used, it is kept for backwards compatibility with
123
+ # earlier versions of rack.
124
+ def normalize_params(params, name, v, _depth=nil)
125
+ _normalize_params(params, name, v, 0)
126
+ end
127
+
128
+ private def _normalize_params(params, name, v, depth)
129
+ raise ParamsTooDeepError if depth >= param_depth_limit
130
+
131
+ if !name
132
+ # nil name, treat same as empty string (required by tests)
133
+ k = after = ''
134
+ elsif depth == 0
135
+ # Start of parsing, don't treat [] or [ at start of string specially
136
+ if start = name.index('[', 1)
137
+ # Start of parameter nesting, use part before brackets as key
138
+ k = name[0, start]
139
+ after = name[start, name.length]
140
+ else
141
+ # Plain parameter with no nesting
142
+ k = name
143
+ after = ''
144
+ end
145
+ elsif name.start_with?('[]')
146
+ # Array nesting
147
+ k = '[]'
148
+ after = name[2, name.length]
149
+ elsif name.start_with?('[') && (start = name.index(']', 1))
150
+ # Hash nesting, use the part inside brackets as the key
151
+ k = name[1, start-1]
152
+ after = name[start+1, name.length]
153
+ else
154
+ # Probably malformed input, nested but not starting with [
155
+ # treat full name as key for backwards compatibility.
156
+ k = name
157
+ after = ''
158
+ end
159
+
160
+ return if k.empty?
161
+
162
+ if after == ''
163
+ if k == '[]' && depth != 0
164
+ return [v]
165
+ else
166
+ params[k] = v
167
+ end
168
+ elsif after == "["
169
+ params[name] = v
170
+ elsif after == "[]"
171
+ params[k] ||= []
172
+ raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
173
+ params[k] << v
174
+ elsif after.start_with?('[]')
175
+ # Recognize x[][y] (hash inside array) parameters
176
+ unless after[2] == '[' && after.end_with?(']') && (child_key = after[3, after.length-4]) && !child_key.empty? && !child_key.index('[') && !child_key.index(']')
177
+ # Handle other nested array parameters
178
+ child_key = after[2, after.length]
179
+ end
180
+ params[k] ||= []
181
+ raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array)
182
+ if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key)
183
+ _normalize_params(params[k].last, child_key, v, depth + 1)
184
+ else
185
+ params[k] << _normalize_params(make_params, child_key, v, depth + 1)
186
+ end
187
+ else
188
+ params[k] ||= make_params
189
+ raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k])
190
+ params[k] = _normalize_params(params[k], after, v, depth + 1)
191
+ end
192
+
193
+ params
194
+ end
195
+
196
+ def make_params
197
+ @params_class.new
198
+ end
199
+
200
+ def new_depth_limit(param_depth_limit)
201
+ self.class.new @params_class, param_depth_limit
202
+ end
203
+
204
+ private
205
+
206
+ def params_hash_type?(obj)
207
+ obj.kind_of?(@params_class)
208
+ end
209
+
210
+ def params_hash_has_key?(hash, key)
211
+ return false if /\[\]/.match?(key)
212
+
213
+ key.split(/[\[\]]+/).inject(hash) do |h, part|
214
+ next h if part == ''
215
+ return false unless params_hash_type?(h) && h.key?(part)
216
+ h[part]
217
+ end
218
+
219
+ true
220
+ end
221
+
222
+ def each_query_pair(qs, separator, unescaper = nil)
223
+ return if !qs || qs.empty?
224
+
225
+ if qs.bytesize > @bytesize_limit
226
+ raise QueryLimitError, "total query size exceeds limit (#{@bytesize_limit})"
227
+ end
228
+
229
+ pairs = qs.split(separator ? (COMMON_SEP[separator] || /[#{separator}] */n) : DEFAULT_SEP, @params_limit + 1)
230
+
231
+ if pairs.size > @params_limit
232
+ param_count = pairs.size + pairs.last.count(separator || "&")
233
+ raise QueryLimitError, "total number of query parameters (#{param_count}) exceeds limit (#{@params_limit})"
234
+ end
235
+
236
+ if unescaper
237
+ pairs.each do |p|
238
+ next if p.empty?
239
+ k, v = p.split('=', 2).map!(&unescaper)
240
+ yield k, v
241
+ end
242
+ else
243
+ pairs.each do |p|
244
+ next if p.empty?
245
+ k, v = p.split('=', 2).map! { |s| unescape(s) }
246
+ yield k, v
247
+ end
248
+ end
249
+ rescue ArgumentError => e
250
+ raise InvalidParameterError, e.message, e.backtrace
251
+ end
252
+
253
+ def unescape(string, encoding = Encoding::UTF_8)
254
+ URI.decode_www_form_component(string, encoding)
255
+ end
256
+
257
+ class Params < Hash
258
+ alias_method :to_params_hash, :to_h
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ require_relative 'constants'
6
+
7
+ module Rack
8
+ # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
9
+ # the current request to the app at +url+.
10
+ #
11
+ # raise ForwardRequest.new("/not-found")
12
+ #
13
+
14
+ class ForwardRequest < Exception
15
+ attr_reader :url, :env
16
+
17
+ def initialize(url, env = {})
18
+ @url = URI(url)
19
+ @env = env
20
+
21
+ @env[PATH_INFO] = @url.path
22
+ @env[QUERY_STRING] = @url.query if @url.query
23
+ @env[HTTP_HOST] = @url.host if @url.host
24
+ @env[HTTP_PORT] = @url.port if @url.port
25
+ @env[RACK_URL_SCHEME] = @url.scheme if @url.scheme
26
+
27
+ super "forwarding to #{url}"
28
+ end
29
+ end
30
+
31
+ # Rack::Recursive allows applications called down the chain to
32
+ # include data from other applications (by using
33
+ # <tt>rack['rack.recursive.include'][...]</tt> or raise a
34
+ # ForwardRequest to redirect internally.
35
+
36
+ class Recursive
37
+ def initialize(app)
38
+ @app = app
39
+ end
40
+
41
+ def call(env)
42
+ dup._call(env)
43
+ end
44
+
45
+ def _call(env)
46
+ @script_name = env[SCRIPT_NAME]
47
+ @app.call(env.merge(RACK_RECURSIVE_INCLUDE => method(:include)))
48
+ rescue ForwardRequest => req
49
+ call(env.merge(req.env))
50
+ end
51
+
52
+ def include(env, path)
53
+ unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
54
+ path[@script_name.size].nil?)
55
+ raise ArgumentError, "can only include below #{@script_name}, not #{path}"
56
+ end
57
+
58
+ env = env.merge(PATH_INFO => path,
59
+ SCRIPT_NAME => @script_name,
60
+ REQUEST_METHOD => GET,
61
+ "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
62
+ RACK_INPUT => StringIO.new(""))
63
+ @app.call(env)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (C) 2009-2018 Michael Fellinger <m.fellinger@gmail.com>
4
+ # Rack::Reloader is subject to the terms of an MIT-style license.
5
+ # See MIT-LICENSE or https://opensource.org/licenses/MIT.
6
+
7
+ require 'pathname'
8
+
9
+ module Rack
10
+
11
+ # High performant source reloader
12
+ #
13
+ # This class acts as Rack middleware.
14
+ #
15
+ # What makes it especially suited for use in a production environment is that
16
+ # any file will only be checked once and there will only be made one system
17
+ # call stat(2).
18
+ #
19
+ # Please note that this will not reload files in the background, it does so
20
+ # only when actively called.
21
+ #
22
+ # It is performing a check/reload cycle at the start of every request, but
23
+ # also respects a cool down time, during which nothing will be done.
24
+ class Reloader
25
+ def initialize(app, cooldown = 10, backend = Stat)
26
+ @app = app
27
+ @cooldown = cooldown
28
+ @last = (Time.now - cooldown)
29
+ @cache = {}
30
+ @mtimes = {}
31
+ @reload_mutex = Mutex.new
32
+
33
+ extend backend
34
+ end
35
+
36
+ def call(env)
37
+ if @cooldown and Time.now > @last + @cooldown
38
+ if Thread.list.size > 1
39
+ @reload_mutex.synchronize{ reload! }
40
+ else
41
+ reload!
42
+ end
43
+
44
+ @last = Time.now
45
+ end
46
+
47
+ @app.call(env)
48
+ end
49
+
50
+ def reload!(stderr = $stderr)
51
+ rotation do |file, mtime|
52
+ previous_mtime = @mtimes[file] ||= mtime
53
+ safe_load(file, mtime, stderr) if mtime > previous_mtime
54
+ end
55
+ end
56
+
57
+ # A safe Kernel::load, issuing the hooks depending on the results
58
+ def safe_load(file, mtime, stderr = $stderr)
59
+ load(file)
60
+ stderr.puts "#{self.class}: reloaded `#{file}'"
61
+ file
62
+ rescue LoadError, SyntaxError => ex
63
+ stderr.puts ex
64
+ ensure
65
+ @mtimes[file] = mtime
66
+ end
67
+
68
+ module Stat
69
+ def rotation
70
+ files = [$0, *$LOADED_FEATURES].uniq
71
+ paths = ['./', *$LOAD_PATH].uniq
72
+
73
+ files.map{|file|
74
+ next if /\.(so|bundle)$/.match?(file) # cannot reload compiled files
75
+
76
+ found, stat = figure_path(file, paths)
77
+ next unless found && stat && mtime = stat.mtime
78
+
79
+ @cache[file] = found
80
+
81
+ yield(found, mtime)
82
+ }.compact
83
+ end
84
+
85
+ # Takes a relative or absolute +file+ name, a couple possible +paths+ that
86
+ # the +file+ might reside in. Returns the full path and File::Stat for the
87
+ # path.
88
+ def figure_path(file, paths)
89
+ found = @cache[file]
90
+ found = file if !found and Pathname.new(file).absolute?
91
+ found, stat = safe_stat(found)
92
+ return found, stat if found
93
+
94
+ paths.find do |possible_path|
95
+ path = ::File.join(possible_path, file)
96
+ found, stat = safe_stat(path)
97
+ return ::File.expand_path(found), stat if found
98
+ end
99
+
100
+ return false, false
101
+ end
102
+
103
+ def safe_stat(file)
104
+ return unless file
105
+ stat = ::File.stat(file)
106
+ return file, stat if stat.file?
107
+ rescue Errno::ENOENT, Errno::ENOTDIR, Errno::ESRCH
108
+ @cache.delete(file) and false
109
+ end
110
+ end
111
+ end
112
+ end