puma 3.12.6 → 4.3.10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +145 -3
- data/README.md +76 -48
- data/docs/architecture.md +1 -0
- data/docs/deployment.md +24 -4
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/plugins.md +20 -10
- data/docs/restart.md +4 -2
- data/docs/systemd.md +27 -9
- data/docs/tcp_mode.md +96 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +13 -0
- data/ext/puma_http11/http11_parser.c +58 -70
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser_common.rl +4 -4
- data/ext/puma_http11/mini_ssl.c +78 -8
- data/ext/puma_http11/org/jruby/puma/Http11.java +106 -114
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +86 -99
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +72 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -4
- data/ext/puma_http11/puma_http11.c +3 -0
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +37 -29
- data/lib/puma/binder.rb +38 -60
- data/lib/puma/cli.rb +4 -0
- data/lib/puma/client.rb +242 -208
- data/lib/puma/cluster.rb +53 -30
- data/lib/puma/configuration.rb +4 -3
- data/lib/puma/const.rb +22 -18
- data/lib/puma/control_cli.rb +30 -5
- data/lib/puma/dsl.rb +299 -75
- data/lib/puma/events.rb +4 -1
- data/lib/puma/io_buffer.rb +1 -6
- data/lib/puma/launcher.rb +95 -53
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/minissl.rb +35 -17
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/plugin.rb +5 -2
- data/lib/puma/rack/builder.rb +2 -0
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +110 -57
- data/lib/puma/runner.rb +11 -3
- data/lib/puma/server.rb +73 -57
- data/lib/puma/single.rb +3 -3
- data/lib/puma/thread_pool.rb +15 -33
- data/lib/puma/util.rb +1 -6
- data/lib/puma.rb +8 -0
- data/lib/rack/handler/puma.rb +3 -3
- data/tools/docker/Dockerfile +16 -0
- data/tools/jungle/init.d/puma +6 -6
- data/tools/trickletest.rb +0 -1
- metadata +26 -13
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
data/lib/puma/single.rb
CHANGED
@@ -18,7 +18,7 @@ module Puma
|
|
18
18
|
r = @server.running || 0
|
19
19
|
t = @server.pool_capacity || 0
|
20
20
|
m = @server.max_threads || 0
|
21
|
-
%Q!{ "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
|
21
|
+
%Q!{ "started_at": "#{@started_at.utc.iso8601}", "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
|
22
22
|
end
|
23
23
|
|
24
24
|
def restart
|
@@ -26,7 +26,7 @@ module Puma
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def stop
|
29
|
-
@server.stop
|
29
|
+
@server.stop(false) if @server
|
30
30
|
end
|
31
31
|
|
32
32
|
def halt
|
@@ -36,7 +36,7 @@ module Puma
|
|
36
36
|
def stop_blocked
|
37
37
|
log "- Gracefully stopping, waiting for requests to finish"
|
38
38
|
@control.stop(true) if @control
|
39
|
-
@server.stop(true)
|
39
|
+
@server.stop(true) if @server
|
40
40
|
end
|
41
41
|
|
42
42
|
def jruby_daemon?
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -87,8 +87,7 @@ module Puma
|
|
87
87
|
@spawned += 1
|
88
88
|
|
89
89
|
th = Thread.new(@spawned) do |spawned|
|
90
|
-
|
91
|
-
Thread.current.name = 'puma %03i' % spawned if Thread.current.respond_to?(:name=)
|
90
|
+
Puma.set_thread_name 'threadpool %03i' % spawned
|
92
91
|
todo = @todo
|
93
92
|
block = @block
|
94
93
|
mutex = @mutex
|
@@ -190,10 +189,13 @@ module Puma
|
|
190
189
|
# request, it might not be added to the `@todo` array right away.
|
191
190
|
# For example if a slow client has only sent a header, but not a body
|
192
191
|
# then the `@todo` array would stay the same size as the reactor works
|
193
|
-
# to try to buffer the request. In
|
192
|
+
# to try to buffer the request. In that scenario the next call to this
|
194
193
|
# method would not block and another request would be added into the reactor
|
195
194
|
# by the server. This would continue until a fully bufferend request
|
196
195
|
# makes it through the reactor and can then be processed by the thread pool.
|
196
|
+
#
|
197
|
+
# Returns the current number of busy threads, or +nil+ if shutting down.
|
198
|
+
#
|
197
199
|
def wait_until_not_full
|
198
200
|
@mutex.synchronize do
|
199
201
|
while true
|
@@ -203,7 +205,8 @@ module Puma
|
|
203
205
|
# is work queued that cannot be handled by waiting
|
204
206
|
# threads, then accept more work until we would
|
205
207
|
# spin up the max number of threads.
|
206
|
-
|
208
|
+
busy_threads = @spawned - @waiting + @todo.size
|
209
|
+
return busy_threads if @max > busy_threads
|
207
210
|
|
208
211
|
@not_full.wait @mutex
|
209
212
|
end
|
@@ -240,10 +243,12 @@ module Puma
|
|
240
243
|
end
|
241
244
|
end
|
242
245
|
|
243
|
-
class
|
244
|
-
def initialize(pool, timeout)
|
246
|
+
class Automaton
|
247
|
+
def initialize(pool, timeout, thread_name, message)
|
245
248
|
@pool = pool
|
246
249
|
@timeout = timeout
|
250
|
+
@thread_name = thread_name
|
251
|
+
@message = message
|
247
252
|
@running = false
|
248
253
|
end
|
249
254
|
|
@@ -251,8 +256,9 @@ module Puma
|
|
251
256
|
@running = true
|
252
257
|
|
253
258
|
@thread = Thread.new do
|
259
|
+
Puma.set_thread_name @thread_name
|
254
260
|
while @running
|
255
|
-
@pool.
|
261
|
+
@pool.public_send(@message)
|
256
262
|
sleep @timeout
|
257
263
|
end
|
258
264
|
end
|
@@ -265,36 +271,12 @@ module Puma
|
|
265
271
|
end
|
266
272
|
|
267
273
|
def auto_trim!(timeout=30)
|
268
|
-
@auto_trim =
|
274
|
+
@auto_trim = Automaton.new(self, timeout, "threadpool trimmer", :trim)
|
269
275
|
@auto_trim.start!
|
270
276
|
end
|
271
277
|
|
272
|
-
class Reaper
|
273
|
-
def initialize(pool, timeout)
|
274
|
-
@pool = pool
|
275
|
-
@timeout = timeout
|
276
|
-
@running = false
|
277
|
-
end
|
278
|
-
|
279
|
-
def start!
|
280
|
-
@running = true
|
281
|
-
|
282
|
-
@thread = Thread.new do
|
283
|
-
while @running
|
284
|
-
@pool.reap
|
285
|
-
sleep @timeout
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def stop
|
291
|
-
@running = false
|
292
|
-
@thread.wakeup
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
278
|
def auto_reap!(timeout=5)
|
297
|
-
@reaper =
|
279
|
+
@reaper = Automaton.new(self, timeout, "threadpool reaper", :reap)
|
298
280
|
@reaper.start!
|
299
281
|
end
|
300
282
|
|
data/lib/puma/util.rb
CHANGED
@@ -1,11 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
|
3
2
|
|
4
|
-
|
5
|
-
require 'puma/rack/backports/uri/common_193'
|
6
|
-
else
|
7
|
-
require 'uri/common'
|
8
|
-
end
|
3
|
+
require 'uri/common'
|
9
4
|
|
10
5
|
module Puma
|
11
6
|
module Util
|
data/lib/puma.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Standard libraries
|
2
4
|
require 'socket'
|
3
5
|
require 'tempfile'
|
@@ -20,4 +22,10 @@ module Puma
|
|
20
22
|
def self.stats
|
21
23
|
@get_stats.stats
|
22
24
|
end
|
25
|
+
|
26
|
+
# Thread name is new in Ruby 2.3
|
27
|
+
def self.set_thread_name(name)
|
28
|
+
return unless Thread.current.respond_to?(:name=)
|
29
|
+
Thread.current.name = "puma #{name}"
|
30
|
+
end
|
23
31
|
end
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rack/handler'
|
2
4
|
|
3
5
|
module Rack
|
@@ -59,8 +61,6 @@ module Rack
|
|
59
61
|
conf
|
60
62
|
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
64
|
def self.run(app, options = {})
|
65
65
|
conf = self.config(app, options)
|
66
66
|
|
@@ -86,7 +86,7 @@ module Rack
|
|
86
86
|
"Verbose" => "Don't report each request (default: false)"
|
87
87
|
}
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
def self.set_host_port_to_config(host, port, config)
|
91
91
|
config.clear_binds! if host || port
|
92
92
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Use this Dockerfile to create minimal reproductions of issues
|
2
|
+
|
3
|
+
FROM ruby:2.6
|
4
|
+
|
5
|
+
# throw errors if Gemfile has been modified since Gemfile.lock
|
6
|
+
RUN bundle config --global frozen 1
|
7
|
+
|
8
|
+
WORKDIR /usr/src/app
|
9
|
+
|
10
|
+
COPY . .
|
11
|
+
RUN gem install bundler
|
12
|
+
RUN bundle install
|
13
|
+
RUN bundle exec rake compile
|
14
|
+
|
15
|
+
EXPOSE 9292
|
16
|
+
CMD bundle exec bin/puma test/rackup/hello.ru
|
data/tools/jungle/init.d/puma
CHANGED
@@ -47,11 +47,11 @@ do_start_one() {
|
|
47
47
|
PIDFILE=$1/tmp/puma/pid
|
48
48
|
if [ -e $PIDFILE ]; then
|
49
49
|
PID=`cat $PIDFILE`
|
50
|
-
# If the puma
|
50
|
+
# If the puma is running, restart it, otherwise run it.
|
51
51
|
if ps -p $PID > /dev/null; then
|
52
|
-
do_start_one_do $1
|
53
|
-
else
|
54
52
|
do_restart_one $1
|
53
|
+
else
|
54
|
+
do_start_one_do $1
|
55
55
|
fi
|
56
56
|
else
|
57
57
|
do_start_one_do $1
|
@@ -106,8 +106,6 @@ do_stop_one() {
|
|
106
106
|
if [ -e $PIDFILE ]; then
|
107
107
|
PID=`cat $PIDFILE`
|
108
108
|
if ps -p $PID > /dev/null; then
|
109
|
-
log_daemon_msg "---> Puma $1 isn't running."
|
110
|
-
else
|
111
109
|
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
|
112
110
|
if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
|
113
111
|
cd $1 && bundle exec pumactl --state $STATEFILE stop
|
@@ -116,6 +114,8 @@ do_stop_one() {
|
|
116
114
|
fi
|
117
115
|
# Many daemons don't delete their pidfiles when they exit.
|
118
116
|
rm -f $PIDFILE $STATEFILE
|
117
|
+
else
|
118
|
+
log_daemon_msg "---> Puma $1 isn't running."
|
119
119
|
fi
|
120
120
|
else
|
121
121
|
log_daemon_msg "---> No puma here..."
|
@@ -398,7 +398,7 @@ case "$1" in
|
|
398
398
|
;;
|
399
399
|
remove)
|
400
400
|
if [ "$#" -lt 2 ]; then
|
401
|
-
echo "Please,
|
401
|
+
echo "Please, specify the app's directory to remove."
|
402
402
|
exit 1
|
403
403
|
else
|
404
404
|
do_remove $2
|
data/tools/trickletest.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 4.3.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2021-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '2.0'
|
19
|
+
name: nio4r
|
20
|
+
prerelease: false
|
21
|
+
type: :runtime
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
13
27
|
description: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server
|
14
28
|
for Ruby/Rack applications. Puma is intended for use in both development and production
|
15
29
|
environments. It's great for highly concurrent Ruby implementations such as Rubinius
|
@@ -39,6 +53,7 @@ files:
|
|
39
53
|
- docs/restart.md
|
40
54
|
- docs/signals.md
|
41
55
|
- docs/systemd.md
|
56
|
+
- docs/tcp_mode.md
|
42
57
|
- ext/puma_http11/PumaHttp11Service.java
|
43
58
|
- ext/puma_http11/ext_help.h
|
44
59
|
- ext/puma_http11/extconf.rb
|
@@ -51,6 +66,7 @@ files:
|
|
51
66
|
- ext/puma_http11/mini_ssl.c
|
52
67
|
- ext/puma_http11/org/jruby/puma/Http11.java
|
53
68
|
- ext/puma_http11/org/jruby/puma/Http11Parser.java
|
69
|
+
- ext/puma_http11/org/jruby/puma/IOBuffer.java
|
54
70
|
- ext/puma_http11/org/jruby/puma/MiniSSL.java
|
55
71
|
- ext/puma_http11/puma_http11.c
|
56
72
|
- lib/puma.rb
|
@@ -61,25 +77,20 @@ files:
|
|
61
77
|
- lib/puma/client.rb
|
62
78
|
- lib/puma/cluster.rb
|
63
79
|
- lib/puma/commonlogger.rb
|
64
|
-
- lib/puma/compat.rb
|
65
80
|
- lib/puma/configuration.rb
|
66
81
|
- lib/puma/const.rb
|
67
82
|
- lib/puma/control_cli.rb
|
68
|
-
- lib/puma/convenient.rb
|
69
|
-
- lib/puma/daemon_ext.rb
|
70
|
-
- lib/puma/delegation.rb
|
71
83
|
- lib/puma/detect.rb
|
72
84
|
- lib/puma/dsl.rb
|
73
85
|
- lib/puma/events.rb
|
74
86
|
- lib/puma/io_buffer.rb
|
75
|
-
- lib/puma/java_io_buffer.rb
|
76
87
|
- lib/puma/jruby_restart.rb
|
77
88
|
- lib/puma/launcher.rb
|
78
89
|
- lib/puma/minissl.rb
|
90
|
+
- lib/puma/minissl/context_builder.rb
|
79
91
|
- lib/puma/null_io.rb
|
80
92
|
- lib/puma/plugin.rb
|
81
93
|
- lib/puma/plugin/tmp_restart.rb
|
82
|
-
- lib/puma/rack/backports/uri/common_193.rb
|
83
94
|
- lib/puma/rack/builder.rb
|
84
95
|
- lib/puma/rack/urlmap.rb
|
85
96
|
- lib/puma/rack_default.rb
|
@@ -92,6 +103,7 @@ files:
|
|
92
103
|
- lib/puma/thread_pool.rb
|
93
104
|
- lib/puma/util.rb
|
94
105
|
- lib/rack/handler/puma.rb
|
106
|
+
- tools/docker/Dockerfile
|
95
107
|
- tools/jungle/README.md
|
96
108
|
- tools/jungle/init.d/README.md
|
97
109
|
- tools/jungle/init.d/puma
|
@@ -108,7 +120,8 @@ licenses:
|
|
108
120
|
- BSD-3-Clause
|
109
121
|
metadata:
|
110
122
|
msys2_mingw_dependencies: openssl
|
111
|
-
|
123
|
+
changelog_uri: https://github.com/puma/puma/blob/master/History.md
|
124
|
+
post_install_message:
|
112
125
|
rdoc_options: []
|
113
126
|
require_paths:
|
114
127
|
- lib
|
@@ -123,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
136
|
- !ruby/object:Gem::Version
|
124
137
|
version: '0'
|
125
138
|
requirements: []
|
126
|
-
rubygems_version: 3.
|
127
|
-
signing_key:
|
139
|
+
rubygems_version: 3.1.6
|
140
|
+
signing_key:
|
128
141
|
specification_version: 4
|
129
142
|
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|
130
143
|
Ruby/Rack applications
|
data/lib/puma/compat.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Provides code to work properly on 1.8 and 1.9
|
2
|
-
|
3
|
-
class String
|
4
|
-
unless method_defined? :bytesize
|
5
|
-
alias_method :bytesize, :size
|
6
|
-
end
|
7
|
-
|
8
|
-
unless method_defined? :byteslice
|
9
|
-
def byteslice(*arg)
|
10
|
-
enc = self.encoding
|
11
|
-
self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/puma/convenient.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'puma/launcher'
|
4
|
-
require 'puma/configuration'
|
5
|
-
|
6
|
-
module Puma
|
7
|
-
def self.run(opts={})
|
8
|
-
cfg = Puma::Configuration.new do |user_config|
|
9
|
-
if port = opts[:port]
|
10
|
-
user_config.port port
|
11
|
-
end
|
12
|
-
|
13
|
-
user_config.quiet
|
14
|
-
|
15
|
-
yield c
|
16
|
-
end
|
17
|
-
|
18
|
-
cfg.clamp
|
19
|
-
|
20
|
-
events = Puma::Events.null
|
21
|
-
|
22
|
-
launcher = Puma::Launcher.new cfg, :events => events
|
23
|
-
launcher.run
|
24
|
-
end
|
25
|
-
end
|
data/lib/puma/daemon_ext.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Process
|
4
|
-
|
5
|
-
# This overrides the default version because it is broken if it
|
6
|
-
# exists.
|
7
|
-
|
8
|
-
if respond_to? :daemon
|
9
|
-
class << self
|
10
|
-
remove_method :daemon
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.daemon(nochdir=false, noclose=false)
|
15
|
-
exit if fork # Parent exits, child continues.
|
16
|
-
|
17
|
-
Process.setsid # Become session leader.
|
18
|
-
|
19
|
-
exit if fork # Zap session leader. See [1].
|
20
|
-
|
21
|
-
Dir.chdir "/" unless nochdir # Release old working directory.
|
22
|
-
|
23
|
-
if !noclose
|
24
|
-
STDIN.reopen File.open("/dev/null", "r")
|
25
|
-
|
26
|
-
null_out = File.open "/dev/null", "w"
|
27
|
-
STDOUT.reopen null_out
|
28
|
-
STDERR.reopen null_out
|
29
|
-
end
|
30
|
-
|
31
|
-
0
|
32
|
-
end
|
33
|
-
end
|
data/lib/puma/delegation.rb
DELETED
data/lib/puma/java_io_buffer.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'java'
|
4
|
-
|
5
|
-
# Conservative native JRuby/Java implementation of IOBuffer
|
6
|
-
# backed by a ByteArrayOutputStream and conversion between
|
7
|
-
# Ruby String and Java bytes
|
8
|
-
module Puma
|
9
|
-
class JavaIOBuffer < java.io.ByteArrayOutputStream
|
10
|
-
field_reader :buf
|
11
|
-
end
|
12
|
-
|
13
|
-
class IOBuffer
|
14
|
-
BUF_DEFAULT_SIZE = 4096
|
15
|
-
|
16
|
-
def initialize
|
17
|
-
@buf = JavaIOBuffer.new(BUF_DEFAULT_SIZE)
|
18
|
-
end
|
19
|
-
|
20
|
-
def reset
|
21
|
-
@buf.reset
|
22
|
-
end
|
23
|
-
|
24
|
-
def <<(str)
|
25
|
-
bytes = str.to_java_bytes
|
26
|
-
@buf.write(bytes, 0, bytes.length)
|
27
|
-
end
|
28
|
-
|
29
|
-
def append(*strs)
|
30
|
-
strs.each { |s| self << s; }
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_s
|
34
|
-
String.from_java_bytes @buf.to_byte_array
|
35
|
-
end
|
36
|
-
|
37
|
-
alias_method :to_str, :to_s
|
38
|
-
|
39
|
-
def used
|
40
|
-
@buf.size
|
41
|
-
end
|
42
|
-
|
43
|
-
def capacity
|
44
|
-
@buf.buf.length
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# :stopdoc:
|
2
|
-
|
3
|
-
require 'uri/common'
|
4
|
-
|
5
|
-
# Issue:
|
6
|
-
# http://bugs.ruby-lang.org/issues/5925
|
7
|
-
#
|
8
|
-
# Relevant commit:
|
9
|
-
# https://github.com/ruby/ruby/commit/edb7cdf1eabaff78dfa5ffedfbc2e91b29fa9ca1
|
10
|
-
|
11
|
-
|
12
|
-
module URI
|
13
|
-
begin
|
14
|
-
256.times do |i|
|
15
|
-
TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
|
16
|
-
end
|
17
|
-
TBLENCWWWCOMP_[' '] = '+'
|
18
|
-
TBLENCWWWCOMP_.freeze
|
19
|
-
|
20
|
-
256.times do |i|
|
21
|
-
h, l = i>>4, i&15
|
22
|
-
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
|
23
|
-
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
|
24
|
-
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
|
25
|
-
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
|
26
|
-
end
|
27
|
-
TBLDECWWWCOMP_['+'] = ' '
|
28
|
-
TBLDECWWWCOMP_.freeze
|
29
|
-
rescue Exception
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# :startdoc:
|