rack 2.2.8 → 3.0.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +213 -83
  3. data/CONTRIBUTING.md +53 -47
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +309 -0
  6. data/SPEC.rdoc +174 -126
  7. data/lib/rack/auth/abstract/handler.rb +3 -1
  8. data/lib/rack/auth/abstract/request.rb +3 -1
  9. data/lib/rack/auth/basic.rb +0 -2
  10. data/lib/rack/auth/digest/md5.rb +1 -131
  11. data/lib/rack/auth/digest/nonce.rb +1 -54
  12. data/lib/rack/auth/digest/params.rb +1 -54
  13. data/lib/rack/auth/digest/request.rb +1 -43
  14. data/lib/rack/auth/digest.rb +256 -0
  15. data/lib/rack/body_proxy.rb +3 -1
  16. data/lib/rack/builder.rb +83 -63
  17. data/lib/rack/cascade.rb +2 -0
  18. data/lib/rack/chunked.rb +16 -13
  19. data/lib/rack/common_logger.rb +23 -18
  20. data/lib/rack/conditional_get.rb +18 -15
  21. data/lib/rack/constants.rb +64 -0
  22. data/lib/rack/content_length.rb +12 -16
  23. data/lib/rack/content_type.rb +8 -5
  24. data/lib/rack/deflater.rb +40 -26
  25. data/lib/rack/directory.rb +9 -3
  26. data/lib/rack/etag.rb +14 -23
  27. data/lib/rack/events.rb +4 -0
  28. data/lib/rack/file.rb +2 -0
  29. data/lib/rack/files.rb +15 -17
  30. data/lib/rack/head.rb +9 -8
  31. data/lib/rack/headers.rb +154 -0
  32. data/lib/rack/lint.rb +758 -646
  33. data/lib/rack/lock.rb +2 -5
  34. data/lib/rack/logger.rb +2 -0
  35. data/lib/rack/media_type.rb +1 -1
  36. data/lib/rack/method_override.rb +5 -1
  37. data/lib/rack/mime.rb +8 -0
  38. data/lib/rack/mock.rb +1 -271
  39. data/lib/rack/mock_request.rb +166 -0
  40. data/lib/rack/mock_response.rb +126 -0
  41. data/lib/rack/multipart/generator.rb +7 -5
  42. data/lib/rack/multipart/parser.rb +120 -64
  43. data/lib/rack/multipart/uploaded_file.rb +4 -0
  44. data/lib/rack/multipart.rb +20 -40
  45. data/lib/rack/null_logger.rb +9 -0
  46. data/lib/rack/query_parser.rb +78 -46
  47. data/lib/rack/recursive.rb +2 -0
  48. data/lib/rack/reloader.rb +0 -2
  49. data/lib/rack/request.rb +224 -106
  50. data/lib/rack/response.rb +138 -61
  51. data/lib/rack/rewindable_input.rb +24 -5
  52. data/lib/rack/runtime.rb +7 -6
  53. data/lib/rack/sendfile.rb +30 -25
  54. data/lib/rack/show_exceptions.rb +15 -2
  55. data/lib/rack/show_status.rb +17 -7
  56. data/lib/rack/static.rb +8 -8
  57. data/lib/rack/tempfile_reaper.rb +15 -4
  58. data/lib/rack/urlmap.rb +3 -1
  59. data/lib/rack/utils.rb +202 -176
  60. data/lib/rack/version.rb +9 -4
  61. data/lib/rack.rb +6 -76
  62. metadata +15 -35
  63. data/README.rdoc +0 -320
  64. data/Rakefile +0 -130
  65. data/bin/rackup +0 -5
  66. data/contrib/rack.png +0 -0
  67. data/contrib/rack.svg +0 -150
  68. data/contrib/rack_logo.svg +0 -164
  69. data/contrib/rdoc.css +0 -412
  70. data/example/lobster.ru +0 -6
  71. data/example/protectedlobster.rb +0 -16
  72. data/example/protectedlobster.ru +0 -10
  73. data/lib/rack/core_ext/regexp.rb +0 -14
  74. data/lib/rack/handler/cgi.rb +0 -59
  75. data/lib/rack/handler/fastcgi.rb +0 -100
  76. data/lib/rack/handler/lsws.rb +0 -61
  77. data/lib/rack/handler/scgi.rb +0 -71
  78. data/lib/rack/handler/thin.rb +0 -36
  79. data/lib/rack/handler/webrick.rb +0 -129
  80. data/lib/rack/handler.rb +0 -104
  81. data/lib/rack/lobster.rb +0 -70
  82. data/lib/rack/server.rb +0 -466
  83. data/lib/rack/session/abstract/id.rb +0 -523
  84. data/lib/rack/session/cookie.rb +0 -204
  85. data/lib/rack/session/memcache.rb +0 -10
  86. data/lib/rack/session/pool.rb +0 -85
  87. data/rack.gemspec +0 -46
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'scgi'
4
- require 'stringio'
5
-
6
- module Rack
7
- module Handler
8
- class SCGI < ::SCGI::Processor
9
- attr_accessor :app
10
-
11
- def self.run(app, **options)
12
- options[:Socket] = UNIXServer.new(options[:File]) if options[:File]
13
- new(options.merge(app: app,
14
- host: options[:Host],
15
- port: options[:Port],
16
- socket: options[:Socket])).listen
17
- end
18
-
19
- def self.valid_options
20
- environment = ENV['RACK_ENV'] || 'development'
21
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
22
-
23
- {
24
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
25
- "Port=PORT" => "Port to listen on (default: 8080)",
26
- }
27
- end
28
-
29
- def initialize(settings = {})
30
- @app = settings[:app]
31
- super(settings)
32
- end
33
-
34
- def process_request(request, input_body, socket)
35
- env = Hash[request]
36
- env.delete "HTTP_CONTENT_TYPE"
37
- env.delete "HTTP_CONTENT_LENGTH"
38
- env[REQUEST_PATH], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
39
- env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
40
- env[PATH_INFO] = env[REQUEST_PATH]
41
- env[QUERY_STRING] ||= ""
42
- env[SCRIPT_NAME] = ""
43
-
44
- rack_input = StringIO.new(input_body)
45
- rack_input.set_encoding(Encoding::BINARY)
46
-
47
- env.update(
48
- RACK_VERSION => Rack::VERSION,
49
- RACK_INPUT => rack_input,
50
- RACK_ERRORS => $stderr,
51
- RACK_MULTITHREAD => true,
52
- RACK_MULTIPROCESS => true,
53
- RACK_RUNONCE => false,
54
- RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
55
- )
56
-
57
- status, headers, body = app.call(env)
58
- begin
59
- socket.write("Status: #{status}\r\n")
60
- headers.each do |k, vs|
61
- vs.split("\n").each { |v| socket.write("#{k}: #{v}\r\n")}
62
- end
63
- socket.write("\r\n")
64
- body.each {|s| socket.write(s)}
65
- ensure
66
- body.close if body.respond_to? :close
67
- end
68
- end
69
- end
70
- end
71
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "thin"
4
- require "thin/server"
5
- require "thin/logging"
6
- require "thin/backends/tcp_server"
7
-
8
- module Rack
9
- module Handler
10
- class Thin
11
- def self.run(app, **options)
12
- environment = ENV['RACK_ENV'] || 'development'
13
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
14
-
15
- host = options.delete(:Host) || default_host
16
- port = options.delete(:Port) || 8080
17
- args = [host, port, app, options]
18
- # Thin versions below 0.8.0 do not support additional options
19
- args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
20
- server = ::Thin::Server.new(*args)
21
- yield server if block_given?
22
- server.start
23
- end
24
-
25
- def self.valid_options
26
- environment = ENV['RACK_ENV'] || 'development'
27
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
28
-
29
- {
30
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
31
- "Port=PORT" => "Port to listen on (default: 8080)",
32
- }
33
- end
34
- end
35
- end
36
- end
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'webrick'
4
- require 'stringio'
5
-
6
- # This monkey patch allows for applications to perform their own chunking
7
- # through WEBrick::HTTPResponse if rack is set to true.
8
- class WEBrick::HTTPResponse
9
- attr_accessor :rack
10
-
11
- alias _rack_setup_header setup_header
12
- def setup_header
13
- app_chunking = rack && @header['transfer-encoding'] == 'chunked'
14
-
15
- @chunked = app_chunking if app_chunking
16
-
17
- _rack_setup_header
18
-
19
- @chunked = false if app_chunking
20
- end
21
- end
22
-
23
- module Rack
24
- module Handler
25
- class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
26
- def self.run(app, **options)
27
- environment = ENV['RACK_ENV'] || 'development'
28
- default_host = environment == 'development' ? 'localhost' : nil
29
-
30
- if !options[:BindAddress] || options[:Host]
31
- options[:BindAddress] = options.delete(:Host) || default_host
32
- end
33
- options[:Port] ||= 8080
34
- if options[:SSLEnable]
35
- require 'webrick/https'
36
- end
37
-
38
- @server = ::WEBrick::HTTPServer.new(options)
39
- @server.mount "/", Rack::Handler::WEBrick, app
40
- yield @server if block_given?
41
- @server.start
42
- end
43
-
44
- def self.valid_options
45
- environment = ENV['RACK_ENV'] || 'development'
46
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
47
-
48
- {
49
- "Host=HOST" => "Hostname to listen on (default: #{default_host})",
50
- "Port=PORT" => "Port to listen on (default: 8080)",
51
- }
52
- end
53
-
54
- def self.shutdown
55
- if @server
56
- @server.shutdown
57
- @server = nil
58
- end
59
- end
60
-
61
- def initialize(server, app)
62
- super server
63
- @app = app
64
- end
65
-
66
- def service(req, res)
67
- res.rack = true
68
- env = req.meta_vars
69
- env.delete_if { |k, v| v.nil? }
70
-
71
- rack_input = StringIO.new(req.body.to_s)
72
- rack_input.set_encoding(Encoding::BINARY)
73
-
74
- env.update(
75
- RACK_VERSION => Rack::VERSION,
76
- RACK_INPUT => rack_input,
77
- RACK_ERRORS => $stderr,
78
- RACK_MULTITHREAD => true,
79
- RACK_MULTIPROCESS => false,
80
- RACK_RUNONCE => false,
81
- RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http",
82
- RACK_IS_HIJACK => true,
83
- RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."},
84
- RACK_HIJACK_IO => nil
85
- )
86
-
87
- env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
88
- env[QUERY_STRING] ||= ""
89
- unless env[PATH_INFO] == ""
90
- path, n = req.request_uri.path, env[SCRIPT_NAME].length
91
- env[PATH_INFO] = path[n, path.length - n]
92
- end
93
- env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
94
-
95
- status, headers, body = @app.call(env)
96
- begin
97
- res.status = status.to_i
98
- io_lambda = nil
99
- headers.each { |k, vs|
100
- if k == RACK_HIJACK
101
- io_lambda = vs
102
- elsif k.downcase == "set-cookie"
103
- res.cookies.concat vs.split("\n")
104
- else
105
- # Since WEBrick won't accept repeated headers,
106
- # merge the values per RFC 1945 section 4.2.
107
- res[k] = vs.split("\n").join(", ")
108
- end
109
- }
110
-
111
- if io_lambda
112
- rd, wr = IO.pipe
113
- res.body = rd
114
- res.chunked = true
115
- io_lambda.call wr
116
- elsif body.respond_to?(:to_path)
117
- res.body = ::File.open(body.to_path, 'rb')
118
- else
119
- body.each { |part|
120
- res.body << part
121
- }
122
- end
123
- ensure
124
- body.close if body.respond_to? :close
125
- end
126
- end
127
- end
128
- end
129
- end
data/lib/rack/handler.rb DELETED
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rack
4
- # *Handlers* connect web servers with Rack.
5
- #
6
- # Rack includes Handlers for Thin, WEBrick, FastCGI, CGI, SCGI
7
- # and LiteSpeed.
8
- #
9
- # Handlers usually are activated by calling <tt>MyHandler.run(myapp)</tt>.
10
- # A second optional hash can be passed to include server-specific
11
- # configuration.
12
- module Handler
13
- def self.get(server)
14
- return unless server
15
- server = server.to_s
16
-
17
- unless @handlers.include? server
18
- load_error = try_require('rack/handler', server)
19
- end
20
-
21
- if klass = @handlers[server]
22
- const_get(klass)
23
- else
24
- const_get(server, false)
25
- end
26
-
27
- rescue NameError => name_error
28
- raise load_error || name_error
29
- end
30
-
31
- # Select first available Rack handler given an `Array` of server names.
32
- # Raises `LoadError` if no handler was found.
33
- #
34
- # > pick ['thin', 'webrick']
35
- # => Rack::Handler::WEBrick
36
- def self.pick(server_names)
37
- server_names = Array(server_names)
38
- server_names.each do |server_name|
39
- begin
40
- return get(server_name.to_s)
41
- rescue LoadError, NameError
42
- end
43
- end
44
-
45
- raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
46
- end
47
-
48
- SERVER_NAMES = %w(puma thin falcon webrick).freeze
49
- private_constant :SERVER_NAMES
50
-
51
- def self.default
52
- # Guess.
53
- if ENV.include?("PHP_FCGI_CHILDREN")
54
- Rack::Handler::FastCGI
55
- elsif ENV.include?(REQUEST_METHOD)
56
- Rack::Handler::CGI
57
- elsif ENV.include?("RACK_HANDLER")
58
- self.get(ENV["RACK_HANDLER"])
59
- else
60
- pick SERVER_NAMES
61
- end
62
- end
63
-
64
- # Transforms server-name constants to their canonical form as filenames,
65
- # then tries to require them but silences the LoadError if not found
66
- #
67
- # Naming convention:
68
- #
69
- # Foo # => 'foo'
70
- # FooBar # => 'foo_bar.rb'
71
- # FooBAR # => 'foobar.rb'
72
- # FOObar # => 'foobar.rb'
73
- # FOOBAR # => 'foobar.rb'
74
- # FooBarBaz # => 'foo_bar_baz.rb'
75
- def self.try_require(prefix, const_name)
76
- file = const_name.gsub(/^[A-Z]+/) { |pre| pre.downcase }.
77
- gsub(/[A-Z]+[^A-Z]/, '_\&').downcase
78
-
79
- require(::File.join(prefix, file))
80
- nil
81
- rescue LoadError => error
82
- error
83
- end
84
-
85
- def self.register(server, klass)
86
- @handlers ||= {}
87
- @handlers[server.to_s] = klass.to_s
88
- end
89
-
90
- autoload :CGI, "rack/handler/cgi"
91
- autoload :FastCGI, "rack/handler/fastcgi"
92
- autoload :WEBrick, "rack/handler/webrick"
93
- autoload :LSWS, "rack/handler/lsws"
94
- autoload :SCGI, "rack/handler/scgi"
95
- autoload :Thin, "rack/handler/thin"
96
-
97
- register 'cgi', 'Rack::Handler::CGI'
98
- register 'fastcgi', 'Rack::Handler::FastCGI'
99
- register 'webrick', 'Rack::Handler::WEBrick'
100
- register 'lsws', 'Rack::Handler::LSWS'
101
- register 'scgi', 'Rack::Handler::SCGI'
102
- register 'thin', 'Rack::Handler::Thin'
103
- end
104
- end
data/lib/rack/lobster.rb DELETED
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'zlib'
4
-
5
- module Rack
6
- # Paste has a Pony, Rack has a Lobster!
7
- class Lobster
8
- LobsterString = Zlib::Inflate.inflate("eJx9kEEOwyAMBO99xd7MAcytUhPlJyj2
9
- P6jy9i4k9EQyGAnBarEXeCBqSkntNXsi/ZCvC48zGQoZKikGrFMZvgS5ZHd+aGWVuWwhVF0
10
- t1drVmiR42HcWNz5w3QanT+2gIvTVCiE1lm1Y0eU4JGmIIbaKwextKn8rvW+p5PIwFl8ZWJ
11
- I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0])
12
-
13
- LambdaLobster = lambda { |env|
14
- if env[QUERY_STRING].include?("flip")
15
- lobster = LobsterString.split("\n").
16
- map { |line| line.ljust(42).reverse }.
17
- join("\n")
18
- href = "?"
19
- else
20
- lobster = LobsterString
21
- href = "?flip"
22
- end
23
-
24
- content = ["<title>Lobstericious!</title>",
25
- "<pre>", lobster, "</pre>",
26
- "<a href='#{href}'>flip!</a>"]
27
- length = content.inject(0) { |a, e| a + e.size }.to_s
28
- [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
29
- }
30
-
31
- def call(env)
32
- req = Request.new(env)
33
- if req.GET["flip"] == "left"
34
- lobster = LobsterString.split("\n").map do |line|
35
- line.ljust(42).reverse.
36
- gsub('\\', 'TEMP').
37
- gsub('/', '\\').
38
- gsub('TEMP', '/').
39
- gsub('{', '}').
40
- gsub('(', ')')
41
- end.join("\n")
42
- href = "?flip=right"
43
- elsif req.GET["flip"] == "crash"
44
- raise "Lobster crashed"
45
- else
46
- lobster = LobsterString
47
- href = "?flip=left"
48
- end
49
-
50
- res = Response.new
51
- res.write "<title>Lobstericious!</title>"
52
- res.write "<pre>"
53
- res.write lobster
54
- res.write "</pre>"
55
- res.write "<p><a href='#{href}'>flip!</a></p>"
56
- res.write "<p><a href='?flip=crash'>crash!</a></p>"
57
- res.finish
58
- end
59
-
60
- end
61
- end
62
-
63
- if $0 == __FILE__
64
- # :nocov:
65
- require_relative '../rack'
66
- Rack::Server.start(
67
- app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
68
- )
69
- # :nocov:
70
- end