rack 2.2.8 → 3.0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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 +9 -4
  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 +208 -178
  60. data/lib/rack/version.rb +9 -4
  61. data/lib/rack.rb +6 -76
  62. metadata +14 -34
  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