Updated documentation in preparation for Rack 3.0.0 release. (#1943)
This commit is contained in:
parent
1e4c18d895
commit
db43fc24ed
|
@ -0,0 +1,8 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
298
README.rdoc
298
README.rdoc
|
@ -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].
|
|
@ -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.
|
Loading…
Reference in New Issue