summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig8
-rw-r--r--CHANGELOG.md2
-rw-r--r--CONTRIBUTING.md86
-rw-r--r--README.md287
-rw-r--r--README.rdoc298
-rw-r--r--UPGRADE-GUIDE.md260
6 files changed, 600 insertions, 341 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..ee510310
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 076783e0..7c986955 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
-## [3.0.0] - Unreleased
+## [3.0.0.beta1] - 2022-08-05
### Security
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 95db71b9..bd5a5120 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,21 +1,25 @@
-Contributing to Rack
-=====================
+# Contributing to Rack
-Rack is work of [hundreds of contributors](https://github.com/rack/rack/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rack/rack/pulls), [propose features and discuss issues](https://github.com/rack/rack/issues). When in doubt, post to the [rack-devel](http://groups.google.com/group/rack-devel) mailing list.
+Rack is work of [hundreds of
+contributors](https://github.com/rack/rack/graphs/contributors). You're
+encouraged to submit [pull requests](https://github.com/rack/rack/pulls) and
+[propose features and discuss issues](https://github.com/rack/rack/issues).
-#### Fork the Project
+## Fork the Project
-Fork the [project on GitHub](https://github.com/rack/rack) and check out your copy.
+Fork the [project on GitHub](https://github.com/rack/rack) and check out your
+copy.
```
-git clone https://github.com/contributor/rack.git
+git clone https://github.com/(your-github-username)/rack.git
cd rack
git remote add upstream https://github.com/rack/rack.git
```
-#### Create a Topic Branch
+## Create a Topic Branch
-Make sure your fork is up-to-date and create a topic branch for your feature or bug fix.
+Make sure your fork is up-to-date and create a topic branch for your feature or
+bug fix.
```
git checkout main
@@ -23,7 +27,7 @@ git pull upstream main
git checkout -b my-feature-branch
```
-#### Bundle Install and Quick Test
+## Bundle Install and Quick Test
Ensure that you can build the project and run quick tests.
@@ -32,7 +36,7 @@ bundle install --without extra
bundle exec rake test
```
-#### Running All Tests
+## Running All Tests
Install all dependencies.
@@ -46,25 +50,15 @@ Run all tests.
rake test
```
-The test suite has no dependencies outside of the core Ruby installation and bacon.
+## Write Tests
-Some tests will be skipped if a dependency is not found.
+Try to write a test that reproduces the problem you're trying to fix or
+describes a feature that you want to build.
-To run the test suite completely, you need:
+We definitely appreciate pull requests that highlight or reproduce a problem,
+even without a fix.
- * fcgi
- * dalli
- * thin
-
-To test Memcache sessions, you need memcached (will be run on port 11211) and dalli installed.
-
-#### Write Tests
-
-Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build.
-
-We definitely appreciate pull requests that highlight or reproduce a problem, even without a fix.
-
-#### Write Code
+## Write Code
Implement your feature or bug fix.
@@ -74,15 +68,15 @@ Make sure that all tests pass:
bundle exec rake test
```
-#### Write Documentation
+## Write Documentation
-Document any external behavior in the [README](README.rdoc).
+Document any external behavior in the [README](README.md).
-#### Update Changelog
+## Update Changelog
Add a line to [CHANGELOG](CHANGELOG.md).
-#### Commit Changes
+## Commit Changes
Make sure git knows your name and email address:
@@ -91,24 +85,27 @@ git config --global user.name "Your Name"
git config --global user.email "contributor@example.com"
```
-Writing good commit logs is important. A commit log should describe what changed and why.
+Writing good commit logs is important. A commit log should describe what changed
+and why.
```
git add ...
git commit
```
-#### Push
+## Push
```
git push origin my-feature-branch
```
-#### Make a Pull Request
+## Make a Pull Request
-Go to https://github.com/contributor/rack and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
+Go to your fork of rack on GitHub and select your feature branch. Click the
+'Pull Request' button and fill out the form. Pull requests are usually
+reviewed within a few days.
-#### Rebase
+## Rebase
If you've been working on a change for a while, rebase with upstream/main.
@@ -118,7 +115,7 @@ git rebase upstream/main
git push origin my-feature-branch -f
```
-#### Make Required Changes
+## Make Required Changes
Amend your previous commit and force push the changes.
@@ -127,14 +124,19 @@ git commit --amend
git push origin my-feature-branch -f
```
-#### Check on Your Pull Request
+## Check on Your Pull Request
-Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
+Go back to your pull request after a few minutes and see whether it passed
+tests with GitHub Actions. Everything should look green, otherwise fix issues and
+amend your commit as described above.
-#### Be Patient
+## Be Patient
-It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
+It's likely that your change will not be merged and that the nitpicky
+maintainers will ask you to do more, or fix seemingly benign problems. Hang in
+there!
-#### Thank You
+## Thank You
-Please do know that we really appreciate and value your time and work. We love you, really.
+Please do know that we really appreciate and value your time and work. We love
+you, really.
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..b3d0c975
--- /dev/null
+++ b/README.md
@@ -0,0 +1,287 @@
+# ![Rack](contrib/logo.webp)
+
+> **_NOTE:_** Rack v3.0.0beta1 was recently released. Please check the [Upgrade
+> Guide](UPGRADE-GUIDE.md) for more details about migrating your existing
+> servers, middlewares and applications. For detailed information on specific
+> changes, check the [Change Log](CHANGELOG.md).
+
+Rack provides a minimal, modular, and adaptable interface for developing web
+applications in Ruby. By wrapping HTTP requests and responses in the simplest
+way possible, it unifies and distills the bridge between web servers, web
+frameworks, and web application into a single method call.
+
+The exact details of this are described in the [Rack Specification], which all
+Rack applications should conform to.
+
+## Installation
+
+Add the rack gem to your application bundle, or follow the instructions provided
+by a [supported web framework](#supported-web-frameworks):
+
+```bash
+# Install it generally:
+$ gem install rack
+
+# or, add it to your current application gemfile:
+$ bundle add rack
+```
+
+## Usage
+
+Create a file called `config.ru` with the following contents:
+
+```ruby
+run do |env|
+ [200, {}, ["Hello World"]]
+end
+```
+
+Run this using the rackup gem or another [supported web
+server](#supported-web-servers).
+
+```bash
+$ gem install rackup
+$ rackup
+$ curl http://localhost:9292
+Hello World
+```
+
+## Supported web servers
+
+Rack is supported by a wide range of servers, including:
+
+* [Agoo](https://github.com/ohler55/agoo)
+* [Falcon](https://github.com/socketry/falcon) **(Rack 3 Compatible)**
+* [Iodine](https://github.com/boazsegev/iodine)
+* [NGINX Unit](https://unit.nginx.org/)
+* [Phusion Passenger](https://www.phusionpassenger.com/) (which is mod_rack for
+ Apache and for nginx)
+* [Puma](https://puma.io/)
+* [Thin](https://github.com/macournoyer/thin)
+* [Unicorn](https://yhbt.net/unicorn/)
+* [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/)
+* [Lamby](https://lamby.custominktech.com) (for AWS Lambda)
+
+You will need to consult the server documentation to find out what features and
+limitations they may have. In general, any valid Rack app will run the same on
+all these servers, without changing anything.
+
+### Rackup
+
+Rack provides a separate gem, [rackup](https://github.com/rack/rackup) which is
+a generic interface for running a Rack application on supported servers, which
+include `WEBRick`, `Puma`, `Falcon` and others.
+
+## Supported web frameworks
+
+These frameworks and many others support the [Rack Specification]:
+
+* [Camping](https://github.com/camping/camping)
+* [Hanami](https://hanamirb.org/)
+* [Padrino](https://padrinorb.com/)
+* [Roda](https://github.com/jeremyevans/roda) **(Rack 3 Compatible)**
+* [Ruby on Rails](https://rubyonrails.org/)
+* [Sinatra](https://sinatrarb.com/)
+* [Utopia](https://github.com/socketry/utopia) **(Rack 3 Compatible)**
+* [WABuR](https://github.com/ohler55/wabur)
+
+### Older (possibly unsupported) web frameworks
+
+* [Ramaze](http://ramaze.net/)
+* [Rum](https://github.com/leahneukirchen/rum)
+
+## Available middleware shipped with Rack
+
+Between the server and the framework, Rack can be customized to your
+applications needs using middleware. Rack itself ships with the following
+middleware:
+
+* `Rack::CommonLogger` for creating Apache-style logfiles.
+* `Rack::ConditionalGet` for returning [Not
+ Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304)
+ responses when the response has not changed.
+* `Rack::Config` for modifying the environment before processing the request.
+* `Rack::ContentLength` for setting a `content-length` header based on body
+ size.
+* `Rack::ContentType` for setting a default `content-type` header for responses.
+* `Rack::Deflater` for compressing responses with gzip.
+* `Rack::ETag` for setting `etag` header on bodies that can be buffered.
+* `Rack::Events` for providing easy hooks when a request is received and when
+ the response is sent.
+* `Rack::Files` for serving static files.
+* `Rack::Head` for returning an empty body for HEAD requests.
+* `Rack::Lint` for checking conformance to the [Rack Specification].
+* `Rack::Lock` for serializing requests using a mutex.
+* `Rack::Logger` for setting a logger to handle logging errors.
+* `Rack::MethodOverride` for modifying the request method based on a submitted
+ parameter.
+* `Rack::Recursive` for including data from other paths in the application, and
+ for performing internal redirects.
+* `Rack::Reloader` for reloading files if they have been modified.
+* `Rack::Runtime` for including a response header with the time taken to process
+ the request.
+* `Rack::Sendfile` for working with web servers that can use optimized file
+ serving for file system paths.
+* `Rack::ShowException` for catching unhandled exceptions and presenting them in
+ a nice and helpful way with clickable backtrace.
+* `Rack::ShowStatus` for using nice error pages for empty client error
+ responses.
+* `Rack::Static` for more configurable serving of static files.
+* `Rack::TempfileReaper` for removing temporary files creating during a request.
+
+All these components use the same interface, which is described in detail in the
+[Rack Specification]. These optional components can be used in any way you wish.
+
+### Convenience interfaces
+
+If you want to develop outside of existing frameworks, implement your own ones,
+or develop middleware, Rack provides many helpers to create Rack applications
+quickly and without doing the same web stuff all over:
+
+* `Rack::Request` which also provides query string parsing and multipart
+ handling.
+* `Rack::Response` for convenient generation of HTTP replies and cookie
+ handling.
+* `Rack::MockRequest` and `Rack::MockResponse` for efficient and quick testing
+ of Rack application without real HTTP round-trips.
+* `Rack::Cascade` for trying additional Rack applications if an application
+ returns a not found or method not supported response.
+* `Rack::Directory` for serving files under a given directory, with directory
+ indexes.
+* `Rack::MediaType` for parsing content-type headers.
+* `Rack::Mime` for determining content-type based on file extension.
+* `Rack::RewindableInput` for making any IO object rewindable, using a temporary
+ file buffer.
+* `Rack::URLMap` to route to multiple applications inside the same process.
+
+## Configuration
+
+Rack exposes several configuration parameters to control various features of the
+implementation.
+
+### `param_depth_limit`
+
+```ruby
+Rack::Utils.param_depth_limit = 32 # default
+```
+
+The maximum amount of nesting allowed in parameters. For example, if set to 3,
+this query string would be allowed:
+
+```
+?a[b][c]=d
+```
+
+but this query string would not be allowed:
+
+```
+?a[b][c][d]=e
+```
+
+Limiting the depth prevents a possible stack overflow when parsing parameters.
+
+### `multipart_part_limit`
+
+```ruby
+Rack::Utils.multipart_part_limit = 128 # default
+```
+
+The maximum number of parts a request can contain. Accepting too many parts can
+lead to the server running out of file handles.
+
+The default is 128, which means that a single request can't upload more than 128
+files at once. Set to 0 for no limit.
+
+Can also be set via the `RACK_MULTIPART_PART_LIMIT` environment variable.
+
+## Changelog
+
+See [CHANGELOG.md](CHANGELOG.md).
+
+## Contributing
+
+See [CONTRIBUTING.md](CONTRIBUTING.md) for specific details about how to make a
+contribution to Rack.
+
+Please post bugs, suggestions and patches to [GitHub
+Issues](https://github.com/rack/rack/issues).
+
+Please check our [Security Policy](https://github.com/rack/rack/security/policy)
+for responsible disclosure and security bug reporting process. Due to wide usage
+of the library, it is strongly preferred that we manage timing in order to
+provide viable patches at the time of disclosure. Your assistance in this matter
+is greatly appreciated.
+
+## See Also
+
+### `rack-contrib`
+
+The plethora of useful middleware created the need for a project that collects
+fresh Rack middleware. `rack-contrib` includes a variety of add-on components
+for Rack and it is easy to contribute new modules.
+
+* https://github.com/rack/rack-contrib
+
+### `rack-session`
+
+Provides convenient session management for Rack.
+
+* https://github.com/rack/rack-session
+
+## Thanks
+
+The Rack Core Team, consisting of
+
+* Aaron Patterson [tenderlove](https://github.com/tenderlove)
+* Samuel Williams [ioquatix](https://github.com/ioquatix)
+* Jeremy Evans [jeremyevans](https://github.com/jeremyevans)
+* Eileen Uchitelle [eileencodes](https://github.com/eileencodes)
+* Matthew Draper [matthewd](https://github.com/matthewd)
+* Rafael França [rafaelfranca](https://github.com/rafaelfranca)
+
+and the Rack Alumni
+
+* Ryan Tomayko [rtomayko](https://github.com/rtomayko)
+* Scytrin dai Kinthra [scytrin](https://github.com/scytrin)
+* Leah Neukirchen [leahneukirchen](https://github.com/leahneukirchen)
+* James Tucker [raggi](https://github.com/raggi)
+* Josh Peek [josh](https://github.com/josh)
+* José Valim [josevalim](https://github.com/josevalim)
+* Michael Fellinger [manveru](https://github.com/manveru)
+* Santiago Pastorino [spastorino](https://github.com/spastorino)
+* Konstantin Haase [rkh](https://github.com/rkh)
+
+would like to thank:
+
+* Adrian Madrid, for the LiteSpeed handler.
+* Christoffer Sawicki, for the first Rails adapter and `Rack::Deflater`.
+* Tim Fletcher, for the HTTP authentication code.
+* Luc Heinrich for the Cookie sessions, the static file handler and bugfixes.
+* Armin Ronacher, for the logo and racktools.
+* Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben Alpert, Dan
+ Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson, Phil Hagelberg, S. Brent
+ Faulkner, Bosko Milekic, Daniel Rodríguez Troitiño, Genki Takiuchi, Geoffrey
+ Grosenbach, Julien Sanchez, Kamal Fariz Mahyuddin, Masayoshi Takahashi,
+ Patrick Aljordm, Mig, Kazuhiro Nishiyama, Jon Bardin, Konstantin Haase, Larry
+ Siden, Matias Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin,
+ and Zach Brock for bug fixing and other improvements.
+* Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support and API
+ improvements.
+* Yehuda Katz and Carl Lerche for refactoring rackup.
+* Brian Candler, for `Rack::ContentType`.
+* Graham Batty, for improved handler loading.
+* Stephen Bannasch, for bug reports and documentation.
+* Gary Wright, for proposing a better `Rack::Response` interface.
+* Jonathan Buch, for improvements regarding `Rack::Response`.
+* Armin Röhrl, for tracking down bugs in the Cookie generator.
+* Alexander Kellett for testing the Gem and reviewing the announcement.
+* Marcus Rückert, for help with configuring and debugging lighttpd.
+* The WSGI team for the well-done and documented work they've done and Rack
+ builds up on.
+* All bug reporters and patch contributors not mentioned above.
+
+## License
+
+Rack is released under the [MIT License](MIT-LICENSE).
+
+[Rack Specification]: SPEC.rdoc
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100644
index 7398c892..00000000
--- a/README.rdoc
+++ /dev/null
@@ -1,298 +0,0 @@
-= rdoc-image:contrib/logo.webp
-
-{<img src="https://github.com/rack/rack/workflows/Development/badge.svg" alt="GitHub Actions status" />}[https://github.com/rack/rack/actions?query=workflow%3ADevelopment]
-{<img src="https://badge.fury.io/rb/rack.svg" alt="Gem Version" />}[http://badge.fury.io/rb/rack]
-{<img src="http://inch-ci.org/github/rack/rack.svg?branch=main" alt="Inline docs" />}[http://inch-ci.org/github/rack/rack]
-
-\Rack provides a minimal, modular, and adaptable interface for developing
-web applications in Ruby. By wrapping HTTP requests and responses in
-the simplest way possible, it unifies and distills the API for web
-servers, web frameworks, and software in between (the so-called
-middleware) into a single method call.
-
-The exact details of this are described in the {\Rack specification}[link:SPEC.rdoc],
-which all \Rack applications should conform to.
-
-== Supported web servers
-
-The included *handlers* can connect these web servers to \Rack:
-
-* WEBrick[https://github.com/ruby/webrick]
-* CGI
-
-These web servers include \Rack handlers in their distributions:
-
-* Agoo[https://github.com/ohler55/agoo]
-* Falcon[https://github.com/socketry/falcon]
-* Iodine[https://github.com/boazsegev/iodine]
-* {NGINX Unit}[https://unit.nginx.org/]
-* {Phusion Passenger}[https://www.phusionpassenger.com/] (which is mod_rack for Apache and for nginx)
-* Puma[https://puma.io/]
-* Thin[https://rubygems.org/gems/thin]
-* Unicorn[https://yhbt.net/unicorn/]
-* uWSGI[https://uwsgi-docs.readthedocs.io/en/latest/]
-* Lamby[https://lamby.custominktech.com] (for AWS Lambda)
-
-Any valid \Rack app will run the same on all these handlers, without
-changing anything.
-
-== Supported web frameworks
-
-These frameworks and many others support the \Rack API:
-
-* Camping[http://www.ruby-camping.com/]
-* Coset[http://leahneukirchen.org/repos/coset/]
-* Hanami[https://hanamirb.org/]
-* Padrino[http://padrinorb.com/]
-* Ramaze[http://ramaze.net/]
-* Roda[https://github.com/jeremyevans/roda]
-* {Ruby on Rails}[https://rubyonrails.org/]
-* Rum[https://github.com/leahneukirchen/rum]
-* Sinatra[http://sinatrarb.com/]
-* Utopia[https://github.com/socketry/utopia]
-* WABuR[https://github.com/ohler55/wabur]
-
-== Available middleware shipped with \Rack
-
-Between the server and the framework, \Rack can be customized to your
-applications needs using middleware. \Rack itself ships with the following
-middleware:
-
-* Rack::Chunked, for streaming responses using chunked encoding.
-* Rack::CommonLogger, for creating Apache-style logfiles.
-* Rack::ConditionalGet, for returning not modified responses when the response
- has not changed.
-* Rack::Config, for modifying the environment before processing the request.
-* Rack::ContentLength, for setting content-length header based on body size.
-* Rack::ContentType, for setting default content-type header for responses.
-* Rack::Deflater, for compressing responses with gzip.
-* Rack::ETag, for setting ETag header on string bodies.
-* Rack::Events, for providing easy hooks when a request is received
- and when the response is sent.
-* Rack::Files, for serving static files.
-* Rack::Head, for returning an empty body for HEAD requests.
-* Rack::Lint, for checking conformance to the \Rack API.
-* Rack::Lock, for serializing requests using a mutex.
-* Rack::Logger, for setting a logger to handle logging errors.
-* Rack::MethodOverride, for modifying the request method based on a submitted
- parameter.
-* Rack::Recursive, for including data from other paths in the application,
- and for performing internal redirects.
-* Rack::Reloader, for reloading files if they have been modified.
-* Rack::Runtime, for including a response header with the time taken to
- process the request.
-* Rack::Sendfile, for working with web servers that can use optimized
- file serving for file system paths.
-* Rack::ShowException, for catching unhandled exceptions and
- presenting them in a nice and helpful way with clickable backtrace.
-* Rack::ShowStatus, for using nice error pages for empty client error
- responses.
-* Rack::Static, for more configurable serving of static files.
-* Rack::TempfileReaper, for removing temporary files creating during a
- request.
-
-All these components use the same interface, which is described in
-detail in the \Rack specification. These optional components can be
-used in any way you wish.
-
-== Convenience
-
-If you want to develop outside of existing frameworks, implement your
-own ones, or develop middleware, \Rack provides many helpers to create
-\Rack applications quickly and without doing the same web stuff all
-over:
-
-* Rack::Request, which also provides query string parsing and
- multipart handling.
-* Rack::Response, for convenient generation of HTTP replies and
- cookie handling.
-* Rack::MockRequest and Rack::MockResponse for efficient and quick
- testing of \Rack application without real HTTP round-trips.
-* Rack::Cascade, for trying additional \Rack applications if an
- application returns a not found or method not supported response.
-* Rack::Directory, for serving files under a given directory, with
- directory indexes.
-* Rack::MediaType, for parsing content-type headers.
-* Rack::Mime, for determining content-type based on file extension.
-* Rack::RewindableInput, for making any IO object rewindable, using
- a temporary file buffer.
-* Rack::URLMap, to route to multiple applications inside the same process.
-
-== rack-contrib
-
-The plethora of useful middleware created the need for a project that
-collects fresh \Rack middleware. rack-contrib includes a variety of
-add-on components for \Rack and it is easy to contribute new modules.
-
-* https://github.com/rack/rack-contrib
-
-== rackup
-
-rackup is a useful tool for running \Rack applications, which uses the
-Rack::Builder DSL to configure middleware and build up applications
-easily.
-
-rackup automatically figures out the environment it is run in, and
-runs your application as FastCGI, CGI, or WEBrick---all from the
-same configuration.
-
-== Quick start
-
-Try the lobster!
-
-Either with the embedded WEBrick starter:
-
- ruby -Ilib lib/rack/lobster.rb
-
-Or with rackup:
-
- bin/rackup -Ilib example/lobster.ru
-
-By default, the lobster is found at http://localhost:9292.
-
-== Installing with RubyGems
-
-A Gem of \Rack is available at {rubygems.org}[https://rubygems.org/gems/rack]. You can install it with:
-
- gem install rack
-
-== Usage
-
-You should require the library:
-
- require 'rack'
-
-\Rack uses autoload to automatically load other files \Rack ships with on demand,
-so you should not need require paths under +rack+. If you require paths under
-+rack+ without requiring +rack+ itself, things may not work correctly.
-
-== Configuration
-
-Several parameters can be modified on Rack::Utils to configure \Rack behaviour.
-
-e.g:
-
- Rack::Utils.param_depth_limit = 3
-
-
-=== param_depth_limit
-
-The maximum amount of nesting allowed in parameters.
-For example, if set to 3, this query string would be allowed:
-
- ?a[b][c]=d
-
-but this query string would not be allowed:
-
- ?a[b][c][d]=e
-
-Limiting the depth prevents a possible stack overflow when parsing parameters.
-
-Defaults to 32.
-
-=== multipart_part_limit
-
-The maximum number of parts a request can contain.
-Accepting too many part can lead to the server running out of file handles.
-
-The default is 128, which means that a single request can't upload more than 128 files at once.
-
-Set to 0 for no limit.
-
-Can also be set via the +RACK_MULTIPART_PART_LIMIT+ environment variable.
-
-=== key_space_limit
-
-No longer has an effect, deprecated.
-
-== Changelog
-
-See {CHANGELOG.md}[link:CHANGELOG.md].
-
-== Contributing
-
-See {CONTRIBUTING.md}[link:CONTRIBUTING.md].
-
-== Contact
-
-Please post bugs, suggestions and patches to
-the bug tracker at {issues}[https://github.com/rack/rack/issues].
-
-Please post security related bugs and suggestions to the core team at
-<https://groups.google.com/forum/#!forum/rack-core> or rack-core@googlegroups.com. This
-list is not public. Due to wide usage of the library, it is strongly preferred
-that we manage timing in order to provide viable patches at the time of
-disclosure. Your assistance in this matter is greatly appreciated.
-
-Mailing list archives are available at
-<https://groups.google.com/forum/#!forum/rack-devel>.
-
-Git repository (send Git patches to the mailing list):
-
-* https://github.com/rack/rack
-
-You are also welcome to join the #rack channel on irc.freenode.net.
-
-== Thanks
-
-The \Rack Core Team, consisting of
-
-* Aaron Patterson (tenderlove[https://github.com/tenderlove])
-* Samuel Williams (ioquatix[https://github.com/ioquatix])
-* Jeremy Evans (jeremyevans[https://github.com/jeremyevans])
-* Eileen Uchitelle (eileencodes[https://github.com/eileencodes])
-* Matthew Draper (matthewd[https://github.com/matthewd])
-* Rafael França (rafaelfranca[https://github.com/rafaelfranca])
-
-and the \Rack Alumni
-
-* Ryan Tomayko (rtomayko[https://github.com/rtomayko])
-* Scytrin dai Kinthra (scytrin[https://github.com/scytrin])
-* Leah Neukirchen (leahneukirchen[https://github.com/leahneukirchen])
-* James Tucker (raggi[https://github.com/raggi])
-* Josh Peek (josh[https://github.com/josh])
-* José Valim (josevalim[https://github.com/josevalim])
-* Michael Fellinger (manveru[https://github.com/manveru])
-* Santiago Pastorino (spastorino[https://github.com/spastorino])
-* Konstantin Haase (rkh[https://github.com/rkh])
-
-would like to thank:
-
-* Adrian Madrid, for the LiteSpeed handler.
-* Christoffer Sawicki, for the first Rails adapter and Rack::Deflater.
-* Tim Fletcher, for the HTTP authentication code.
-* Luc Heinrich for the Cookie sessions, the static file handler and bugfixes.
-* Armin Ronacher, for the logo and racktools.
-* Alex Beregszaszi, Alexander Kahn, Anil Wadghule, Aredridel, Ben
- Alpert, Dan Kubb, Daniel Roethlisberger, Matt Todd, Tom Robinson,
- Phil Hagelberg, S. Brent Faulkner, Bosko Milekic, Daniel Rodríguez
- Troitiño, Genki Takiuchi, Geoffrey Grosenbach, Julien Sanchez, Kamal
- Fariz Mahyuddin, Masayoshi Takahashi, Patrick Aljordm, Mig, Kazuhiro
- Nishiyama, Jon Bardin, Konstantin Haase, Larry Siden, Matias
- Korhonen, Sam Ruby, Simon Chiang, Tim Connor, Timur Batyrshin, and
- Zach Brock for bug fixing and other improvements.
-* Eric Wong, Hongli Lai, Jeremy Kemper for their continuous support
- and API improvements.
-* Yehuda Katz and Carl Lerche for refactoring rackup.
-* Brian Candler, for Rack::ContentType.
-* Graham Batty, for improved handler loading.
-* Stephen Bannasch, for bug reports and documentation.
-* Gary Wright, for proposing a better Rack::Response interface.
-* Jonathan Buch, for improvements regarding Rack::Response.
-* Armin Röhrl, for tracking down bugs in the Cookie generator.
-* Alexander Kellett for testing the Gem and reviewing the announcement.
-* Marcus Rückert, for help with configuring and debugging lighttpd.
-* The WSGI team for the well-done and documented work they've done and
- \Rack builds up on.
-* All bug reporters and patch contributors not mentioned above.
-
-== Links
-
-\Rack:: <https://rack.github.io/>
-Official \Rack repositories:: <https://github.com/rack>
-\Rack Bug Tracking:: <https://github.com/rack/rack/issues>
-rack-devel mailing list:: <https://groups.google.com/forum/#!forum/rack-devel>
-
-== License
-
-\Rack is released under the {MIT License}[https://opensource.org/licenses/MIT].
diff --git a/UPGRADE-GUIDE.md b/UPGRADE-GUIDE.md
new file mode 100644
index 00000000..ca9d428c
--- /dev/null
+++ b/UPGRADE-GUIDE.md
@@ -0,0 +1,260 @@
+# Rack 3 Upgrade Guide
+
+This document is a work in progress, but outlines some of the key changes in
+Rack 3 which you should be aware of in order to update your server, middleware
+and/or applications.
+
+## Interface Changes
+
+### `config.ru` `Rack::Builder#run` now accepts block
+
+Previously, `Rack::Builder#run` method would only accept a callable argument:
+
+```ruby
+run lambda{|env| [200, {}, ["Hello World"]]}
+```
+
+This can be rewritten more simply:
+
+```ruby
+run do |env|
+ [200, {}, ["Hello World"]]
+end
+```
+
+### Response bodies can be used for bi-directional streaming
+
+Previously, the `rack.hijack` response header could be used for implementing
+bi-directional streaming (e.g. WebSockets).
+
+```ruby
+def call(env)
+ stream_callback = proc do |stream|
+ stream.read(...)
+ stream.write(...)
+ ensure
+ stream.close(...)
+ end
+
+ return [200, {'rack.hijack' => stream_callback}, []]
+end
+```
+
+This feature was optional and tricky to use correctly. You can now achieve the
+same thing by giving `stream_callback` as the response body:
+
+```ruby
+def call(env)
+ stream_callback = proc do |stream|
+ stream.read(...)
+ stream.write(...)
+ ensure
+ stream.close(...)
+ end
+
+ return [200, {}, stream_callback]
+end
+```
+
+### `Rack::Session` is now moved to an external gem
+
+Previously, `Rack::Session` was part of the `rack` gem. Not every application
+needs it, and it increases the security surface area of the `rack`, so it was
+decided to extract it into its own gem `rack-session` which can be updated
+independently.
+
+Applications that make use of `rack-session` will need to add that gem as a
+dependency:
+
+```ruby
+gem 'rack-session'
+```
+
+
+## Request Changes
+
+### `rack.version` is no longer required
+
+Previously, the "rack protocol version" was available in `rack.version` but it
+was not practically useful, so it has been removed as a requirement.
+
+### `rack.multithread`/`rack.multiprocess`/`rack.run_once` are no longer required
+
+Previously, servers tried to provide these keys to reflect the execution
+environment. These come too late to be useful, so they have been removed as a
+requirement.
+
+### `rack.hijack?` now only applies to partial hijack
+
+Previously, both full and partial hijiack were controlled by the presence and
+value of `rack.hijack?`. Now, it only applies to partial hijack (which itself
+has been effectively replaced by streaming bodies).
+
+### `rack.hijack` alone indicates that you can execute a full hijack
+
+Previously, `rack.hijack?` had to be truthy, as well as having `rack.hijack`
+present in the request environment. Now, the presence of the `rack.hijack`
+callback is enough.
+
+### `rack.hijack_io` is removed
+
+Previously, the server would try to set `rack.hijack_io` into the request
+environment when `rack.hijack` was invoked for a full hijack. This was often
+impossible if a middleware had called `env.dup`, so this requirement has been
+dropped entirely.
+
+### `rack.input` is no longer required to be rewindable
+
+Previosuly, `rack.input` was required to be rewindable, i.e. `io.seek(0)` but
+this was only generally possible with a file based backing, which prevented
+efficient streaming of request bodies. Now, `rack.input` is not required to be
+rewindable.
+
+## Response Changes
+
+### Response must be mutable
+
+Rack 3 requires the response Array `[status, headers, body]` to be mutable.
+Existing code that uses a frozen response will need to be changed:
+
+```ruby
+NOT_FOUND = [404, {}, ["Not Found"]].freeze
+
+def call(env)
+ ...
+ return NOT_FOUND
+end
+```
+
+should be rewritten as:
+
+```ruby
+def not_found
+ [404, {}, ["Not Found"]]
+end
+
+def call(env)
+ ...
+ return not_found
+end
+```
+
+Note there is a subtle bug in the former version: the headers hash is mutable
+and can be modified, and these modifications can leak into subsequent requests.
+
+### Response headers must be a mutable hash
+
+Rack 3 requires response headers to be a mutable hash. Previously it could be
+any object that would respond to `#each` and yield `key`/`value` pairs.
+Previously, the following was acceptable:
+
+```ruby
+def call(env)
+ return [200, [['content-type', 'text/plain']], ["Hello World]]
+end
+```
+
+Now you must use a hash instance:
+
+```ruby
+def call(env)
+ return [200, {'content-type' => 'text/plain'}, ["Hello World]]
+end
+```
+
+This ensures middleware can predictably update headers as needed.
+
+### Response Headers must be lower case
+
+Rack 3 requires all response headers to be lower case. This is to simplify
+fetching and updating response headers. Previously you had to use something like
+`Rack::HeadersHash`
+
+```ruby
+def call(env)
+ response = @app.call(env)
+ # HeaderHash must allocate internal objects and compute lower case keys:
+ headers = Rack::Utils::HeaderHash[response[1]]
+
+ cache_response(headers['ETag'], response)
+
+ ...
+end
+```
+
+but now you must just use the normal form for HTTP header:
+
+```ruby
+def call(env)
+ response = @app.call(env)
+ # A plain hash with lower case keys:
+ headers = response[1]
+
+ cache_response(headers['etag'], response)
+
+ ...
+end
+```
+
+### Multiple response header values are encoded using an `Array`
+
+Response header values can be an Array to handle multiple values (and no longer
+supports `\n` encoded headers). If you use `Rack::Response`, you don't need to
+do anything, but if manually append values to response headers, you will need to
+promote them to an Array, e.g.
+
+```ruby
+def set_cookie_header!(headers, key, value)
+ if header = headers[SET_COOKIE]
+ if header.is_a?(Array)
+ header << set_cookie_header(key, value)
+ else
+ headers[SET_COOKIE] = [header, set_cookie_header(key, value)]
+ end
+ else
+ headers[SET_COOKIE] = set_cookie_header(key, value)
+ end
+end
+```
+
+### Response body might not respond to `#each`
+
+Rack 3 has more strict requirements on response bodies. Previously, response
+body would only need to respond to `#each` and optionally `#close`. In addition,
+there was no way to determine whether it was safe to call `#each` and buffer the
+response.
+
+### Response bodies can be buffered if they expose `#to_ary`
+
+If your body responds to `#to_ary` then it must return an `Array` whose contents
+are identical to that produced by calling `#each`. If the body responds to both
+`#to_ary` and `#close` then its implementation of `#to_ary` must also call
+`#close`.
+
+Previously, it was not possible to determine whether a response body was
+immediately available (could be buffered) or was streaming chunks. This case is
+now unambiguously exposed by `#to_ary`:
+
+```ruby
+def call(env)
+ status, headers, body = @app.call(env)
+
+ # Check if we can buffer the body into an Array, so we can compute a digest:
+ if body.respond_to?(:to_ary)
+ body = body.to_ary
+ digest = digest_body(body)
+ headers[ETAG_STRING] = %(W/"#{digest}") if digest
+ end
+
+ return [status, headers, body]
+end
+```
+
+### Middleware should not directly modify the response body
+
+Be aware that the response body might not respond to `#each` and you must now
+check if the body responds to `#each` or not to determine if it is an enumerable
+or streaming body.
+
+You must not call `#each` directly on the body and instead you should return a
+new body that calls `#each` on the original body.