Add support for ISO-2022-JP encoding in multipart form data handling (#2247)
[rack.git] / UPGRADE-GUIDE.md
blob5bc39a03d351d320435d8f19daa94bf731021957
1 # Rack 3 Upgrade Guide
3 This document is a work in progress, but outlines some of the key changes in
4 Rack 3 which you should be aware of in order to update your server, middleware
5 and/or applications.
7 ## Interface Changes
9 ### Rack 2 & Rack 3 compatibility
11 Most applications can be compatible with Rack 2 and 3 by following the strict intersection of the Rack Specifications, notably:
13 - Response array must now be non-frozen.
14 - Response `status` must now be an integer greater than or equal to 100.
15 - Response `headers` must now be an unfrozen hash.
16 - Response header keys can no longer include uppercase characters.
17 - `rack.input` is no longer required to be rewindable.
18 - `rack.multithread`/`rack.multiprocess`/`rack.run_once`/`rack.version` are no longer required environment keys.
19 - `rack.hijack?` (partial hijack) and `rack.hijack` (full hijack) are now independently optional.
20 - `rack.hijack_io` has been removed completely.
21 - `SERVER_PROTOCOL` is now a required key, matching the HTTP protocol used in the request.
22 - Middleware must no longer call `#each` on the body, but they can call `#to_ary` on the body if it responds to `#to_ary`.
24 There is one changed feature in Rack 3 which is not backwards compatible:
26 - Response header values can be an `Array` to handle multiple values (and no longer supports `\n` encoded headers).
28 You can achieve compatibility by using `Rack::Response#add_header` which provides an interface for adding headers without concern for the underlying format.
30 There is one new feature in Rack 3 which is not directly backwards compatible:
32 - Response body can now respond to `#call` (streaming body) instead of `#each` (enumerable body), for the equivalent of response hijacking in previous versions.
34 If supported by your server, you can use partial rack hijack instead (or wrap this behaviour in a middleware).
36 ### `config.ru` `Rack::Builder#run` now accepts block
38 Previously, `Rack::Builder#run` method would only accept a callable argument:
40 ```ruby
41 run lambda{|env| [200, {}, ["Hello World"]]}
42 ```
44 This can be rewritten more simply:
46 ```ruby
47 run do |env|
48   [200, {}, ["Hello World"]]
49 end
50 ```
52 ### Response bodies can be used for bi-directional streaming
54 Previously, the `rack.hijack` response header could be used for implementing
55 bi-directional streaming (e.g. WebSockets).
57 ```ruby
58 def call(env)
59   stream_callback = proc do |stream|
60     stream.read(...)
61     stream.write(...)
62   ensure
63     stream.close(...)
64   end
66   return [200, {'rack.hijack' => stream_callback}, []]
67 end
68 ```
70 This feature was optional and tricky to use correctly. You can now achieve the
71 same thing by giving `stream_callback` as the response body:
73 ```ruby
74 def call(env)
75   stream_callback = proc do |stream|
76     stream.read(...)
77     stream.write(...)
78   ensure
79     stream.close(...)
80   end
82   return [200, {}, stream_callback]
83 end
84 ```
86 ### `Rack::Session` was moved to a separate gem.
88 Previously, `Rack::Session` was part of the `rack` gem. Not every application
89 needs it, and it increases the security surface area of the `rack`, so it was
90 decided to extract it into its own gem `rack-session` which can be updated
91 independently.
93 Applications that make use of `rack-session` will need to add that gem as a
94 dependency:
96 ```ruby
97 gem 'rack-session'
98 ```
100 This provides all the previously available functionality.
102 ### `bin/rackup`, `Rack::Server`, `Rack::Handler`and  `Rack::Lobster` were moved to a separate gem.
104 Previously, the `rackup` executable was included with Rack. Because WEBrick is
105 no longer a default gem with Ruby, we had to make a decision: either `rack`
106 should depend on `webrick` or we should move that functionality into a
107 separate gem. We chose the latter which will hopefully allow us to innovate
108 more rapidly on the design and implementation of `rackup` separately from
109 "rack the interface".
111 In Rack 3, you will need to include:
113 ```ruby
114 gem 'rackup'
117 This provides all the previously available functionality.
119 The classes `Rack::Server`, `Rack::Handler` and  `Rack::Lobster` have been moved to the rackup gem too and renamed to `Rackup::Server`, `Rackup::Handler` and  `Rackup::Lobster` respectively.
121 To start an app with `Rackup::Server` with Rack 3 :
123 ```ruby
124 require 'rackup'
125 Rackup::Server.start app: app, Port: 3000
128 #### `config.ru` autoloading is disabled unless `require 'rack'`
130 Previously, rack modules like `rack/directory` were autoloaded because `rackup` did require 'rack'. In Rack 3, you will need to write `require 'rack'` or require specific module explicitly.
132 ```diff
133 +require 'rack'
134 run Rack::Directory.new '.'
139 ```diff
140 +require 'rack/directory'
141 run Rack::Directory.new '.'
144 ## Request Changes
146 ### `rack.version` is no longer required
148 Previously, the "rack protocol version" was available in `rack.version` but it
149 was not practically useful, so it has been removed as a requirement.
151 ### `rack.multithread`/`rack.multiprocess`/`rack.run_once` are no longer required
153 Previously, servers tried to provide these keys to reflect the execution
154 environment. These come too late to be useful, so they have been removed as  a
155 requirement.
157 ### `rack.hijack?` now only applies to partial hijack
159 Previously, both full and partial hijiack were controlled by the presence and
160 value of `rack.hijack?`. Now, it only applies to partial hijack (which now can
161 be replaced by streaming bodies).
163 ### `rack.hijack` alone indicates that you can execute a full hijack
165 Previously, `rack.hijack?` had to be truthy, as well as having `rack.hijack`
166 present in the request environment. Now, the presence of the `rack.hijack`
167 callback is enough.
169 ### `rack.hijack_io` is removed
171 Previously, the server would try to set `rack.hijack_io` into the request
172 environment when `rack.hijack` was invoked for a full hijack. This was often
173 impossible if a middleware had called `env.dup`, so this requirement has been
174 dropped entirely.
176 ### `rack.input` is no longer required to be rewindable
178 Previously, `rack.input` was required to be rewindable, i.e. `io.seek(0)` but
179 this was only generally possible with a file based backing, which prevented
180 efficient streaming of request bodies. Now, `rack.input` is not required to be
181 rewindable.
183 ### `rack.input` is no longer rewound after consuming form and multipart data
185 Previously `.rewind` was called after consuming form and multipart data. Use
186 `Rack::RewindableInput::Middleware` to make the body rewindable, and call
187 `.rewind` explicitly to match this behavior.
189 ### Invalid nested query parsing syntax
191 Previously, Rack 2 was able to parse the query string `a[b[c]]=x` in the same
192 way as `a[b][c]=x`. This invalid syntax was never officially supported. However,
193 some libraries and applications used it anyway. Due to implementation details,
194 Rack 2 ended up parsing it the same as the correct syntax. The implementation
195 was changed in Rack 3, and this invalid syntax is no longer parsed the same way
196 as the correct syntax:
198 ```ruby
199 Rack::Utils.parse_nested_query("a[b[c]]=x")
200 # Rack 3 => {"a"=>{"b[c"=>{"]"=>"x"}}} ❌
201 # Rack 2 => {"a"=>{"b"=>{"c"=>"x"}}} ✅
204 The correct syntax for nested parameters is `a[b][c]=x` and you'll need
205 to change that in your application code to be compatible with Rack 3:
207 ```ruby
208 Rack::Utils.parse_nested_query("a[b][c]=x")
209 # Rack 3 => {"a"=>{"b"=>{"c"=>"x"}}} ✅
210 # Rack 2 => {"a"=>{"b"=>{"c"=>"x"}}} ✅
213 See <https://github.com/rack/rack/issues/2128> for more context.
215 ## Response Changes
217 ### Response must be mutable
219 Rack 3 requires the response Array `[status, headers, body]` to be mutable.
220 Existing code that uses a frozen response will need to be changed:
222 ```ruby
223 NOT_FOUND = [404, {}, ["Not Found"]].freeze
225 def call(env)
226   ...
227   return NOT_FOUND
231 should be rewritten as:
233 ```ruby
234 def not_found
235   [404, {}, ["Not Found"]]
238 def call(env)
239   ...
240   return not_found
244 Note there is a subtle bug in the former version: the headers hash is mutable
245 and can be modified, and these modifications can leak into subsequent requests.
247 ### Response headers must be a mutable hash
249 Rack 3 requires response headers to be a mutable hash. Previously it could be
250 any object that would respond to `#each` and yield `key`/`value` pairs.
251 Previously, the following was acceptable:
253 ```ruby
254 def call(env)
255   return [200, [['content-type', 'text/plain']], ["Hello World"]]
259 Now you must use a hash instance:
261 ```ruby
262 def call(env)
263   return [200, {'content-type' => 'text/plain'}, ["Hello World"]]
267 This ensures middleware can predictably update headers as needed.
269 ### Response Headers must be lower case
271 Rack 3 requires all response headers to be lower case. This is to simplify
272 fetching and updating response headers. Previously you had to use something like
273 `Rack::HeadersHash`
275 ```ruby
276 def call(env)
277   response = @app.call(env)
278   # HeaderHash must allocate internal objects and compute lower case keys:
279   headers = Rack::Utils::HeaderHash[response[1]]
281   cache_response(headers['ETag'], response)
283   ...
287 but now you must just use the normal form for HTTP header:
289 ```ruby
290 def call(env)
291   response = @app.call(env)
292   # A plain hash with lower case keys:
293   headers = response[1]
295   cache_response(headers['etag'], response)
297   ...
301 If you want your code to work with Rack 3 without having to manually lowercase
302 each header key used, instead of using a plain hash for headers, you can use
303 `Rack::Headers` on Rack 3.
305 ```ruby
306   headers = defined?(Rack::Headers) ? Rack::Headers.new : {}
309 `Rack::Headers` is a subclass of Hash that will automatically lowercase keys:
311 ```ruby
312   headers = Rack::Headers.new
313   headers['Foo'] = 'bar'
314   headers['FOO'] # => 'bar'
315   headers.keys   # => ['foo']
318 ### Multiple response header values are encoded using an `Array`
320 Response header values can be an Array to handle multiple values (and no longer
321 supports `\n` encoded headers). If you use `Rack::Response`, you don't need to
322 do anything, but if manually append values to response headers, you will need to
323 promote them to an Array, e.g.
325 ```ruby
326 def set_cookie_header!(headers, key, value)
327   if header = headers[SET_COOKIE]
328     if header.is_a?(Array)
329       header << set_cookie_header(key, value)
330     else
331       headers[SET_COOKIE] = [header, set_cookie_header(key, value)]
332     end
333   else
334     headers[SET_COOKIE] = set_cookie_header(key, value)
335   end
339 ### Response body might not respond to `#each`
341 Rack 3 has more strict requirements on response bodies. Previously, response
342 body would only need to respond to `#each` and optionally `#close`. In addition,
343 there was no way to determine whether it was safe to call `#each` and buffer the
344 response.
346 ### Response bodies can be buffered if they expose `#to_ary`
348 If your body responds to `#to_ary` then it must return an `Array` whose contents
349 are identical to that produced by calling `#each`. If the body responds to both
350 `#to_ary` and `#close` then its implementation of `#to_ary` must also call
351 `#close`.
353 Previously, it was not possible to determine whether a response body was
354 immediately available (could be buffered) or was streaming chunks. This case is
355 now unambiguously exposed by `#to_ary`:
357 ```ruby
358 def call(env)
359   status, headers, body = @app.call(env)
361   # Check if we can buffer the body into an Array, so we can compute a digest:
362   if body.respond_to?(:to_ary)
363     body = body.to_ary
364     digest = digest_body(body)
365     headers[ETAG_STRING] = %(W/"#{digest}") if digest
366   end
368   return [status, headers, body]
372 ### Middleware should not directly modify the response body
374 Be aware that the response body might not respond to `#each` and you must now
375 check if the body responds to `#each` or not to determine if it is an enumerable
376 or streaming body.
378 You must not call `#each` directly on the body and instead you should return a
379 new body that calls `#each` on the original body.
381 ### Status needs to be an `Integer`
383 The response status is now required to be an `Integer` with a value greater or equal to 100.
385 Previously any object that responded to `#to_i` was allowed, so a response like `["200", {}, ""]` will need to be replaced with `[200, {}, ""]` and so on. This can be done by calling `#to_i` on the status object yourself.