Skip to content

Commit 891652d

Browse files
committed
Revert "Lower-case all reseponse headers from Sprockets::Server"
This reverts commit cdab3b8. The lower-case response header in Rack 3 is incompatible with Rack 2. Since Sprockets don't support Rack 3 yet, it is better to keep the behavior compatible with Rack 2. Fix #746.
1 parent 2614054 commit 891652d

File tree

3 files changed

+55
-53
lines changed

3 files changed

+55
-53
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Get upgrade notes from Sprockets 3.x to 4.x at https://github.com/rails/sprockets/blob/master/UPGRADING.md
44

5+
- Fix `Sprockets::Server` to return response headers to compatible with with Rack::Lint 2.0.
6+
57
## 4.1.0
68

79
- Allow age to be altered in asset:clean rake task.

lib/sprockets/server.rb

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -148,39 +148,39 @@ def not_modified_response(env, etag)
148148
# Returns a 400 Forbidden response tuple
149149
def bad_request_response(env)
150150
if head_request?(env)
151-
[ 400, { "content-type" => "text/plain", "content-length" => "0" }, [] ]
151+
[ 400, { "Content-Type" => "text/plain", "Content-Length" => "0" }, [] ]
152152
else
153-
[ 400, { "content-type" => "text/plain", "content-length" => "11" }, [ "Bad Request" ] ]
153+
[ 400, { "Content-Type" => "text/plain", "Content-Length" => "11" }, [ "Bad Request" ] ]
154154
end
155155
end
156156

157157
# Returns a 403 Forbidden response tuple
158158
def forbidden_response(env)
159159
if head_request?(env)
160-
[ 403, { "content-type" => "text/plain", "content-length" => "0" }, [] ]
160+
[ 403, { "Content-Type" => "text/plain", "Content-Length" => "0" }, [] ]
161161
else
162-
[ 403, { "content-type" => "text/plain", "content-length" => "9" }, [ "Forbidden" ] ]
162+
[ 403, { "Content-Type" => "text/plain", "Content-Length" => "9" }, [ "Forbidden" ] ]
163163
end
164164
end
165165

166166
# Returns a 404 Not Found response tuple
167167
def not_found_response(env)
168168
if head_request?(env)
169-
[ 404, { "content-type" => "text/plain", "content-length" => "0", "x-cascade" => "pass" }, [] ]
169+
[ 404, { "Content-Type" => "text/plain", "Content-Length" => "0", "X-Cascade" => "pass" }, [] ]
170170
else
171-
[ 404, { "content-type" => "text/plain", "content-length" => "9", "x-cascade" => "pass" }, [ "Not found" ] ]
171+
[ 404, { "Content-Type" => "text/plain", "Content-Length" => "9", "X-Cascade" => "pass" }, [ "Not found" ] ]
172172
end
173173
end
174174

175175
def method_not_allowed_response
176-
[ 405, { "content-type" => "text/plain", "content-length" => "18" }, [ "Method Not Allowed" ] ]
176+
[ 405, { "Content-Type" => "text/plain", "Content-Length" => "18" }, [ "Method Not Allowed" ] ]
177177
end
178178

179179
def precondition_failed_response(env)
180180
if head_request?(env)
181-
[ 412, { "content-type" => "text/plain", "content-length" => "0", "x-cascade" => "pass" }, [] ]
181+
[ 412, { "Content-Type" => "text/plain", "Content-Length" => "0", "X-Cascade" => "pass" }, [] ]
182182
else
183-
[ 412, { "content-type" => "text/plain", "content-length" => "19", "x-cascade" => "pass" }, [ "Precondition Failed" ] ]
183+
[ 412, { "Content-Type" => "text/plain", "Content-Length" => "19", "X-Cascade" => "pass" }, [ "Precondition Failed" ] ]
184184
end
185185
end
186186

@@ -189,7 +189,7 @@ def precondition_failed_response(env)
189189
def javascript_exception_response(exception)
190190
err = "#{exception.class.name}: #{exception.message}\n (in #{exception.backtrace[0]})"
191191
body = "throw Error(#{err.inspect})"
192-
[ 200, { "content-type" => "application/javascript", "content-length" => body.bytesize.to_s }, [ body ] ]
192+
[ 200, { "Content-Type" => "application/javascript", "Content-Length" => body.bytesize.to_s }, [ body ] ]
193193
end
194194

195195
# Returns a CSS response that hides all elements on the page and
@@ -242,7 +242,7 @@ def css_exception_response(exception)
242242
}
243243
CSS
244244

245-
[ 200, { "content-type" => "text/css; charset=utf-8", "content-length" => body.bytesize.to_s }, [ body ] ]
245+
[ 200, { "Content-Type" => "text/css; charset=utf-8", "Content-Length" => body.bytesize.to_s }, [ body ] ]
246246
end
247247

248248
# Escape special characters for use inside a CSS content("...") string
@@ -258,18 +258,18 @@ def cache_headers(env, etag)
258258
headers = {}
259259

260260
# Set caching headers
261-
headers["cache-control"] = +"public"
262-
headers["etag"] = %("#{etag}")
261+
headers["Cache-Control"] = +"public"
262+
headers["ETag"] = %("#{etag}")
263263

264264
# If the request url contains a fingerprint, set a long
265265
# expires on the response
266266
if path_fingerprint(env["PATH_INFO"])
267-
headers["cache-control"] << ", max-age=31536000, immutable"
267+
headers["Cache-Control"] << ", max-age=31536000, immutable"
268268

269269
# Otherwise set `must-revalidate` since the asset could be modified.
270270
else
271-
headers["cache-control"] << ", must-revalidate"
272-
headers["vary"] = "Accept-Encoding"
271+
headers["Cache-Control"] << ", must-revalidate"
272+
headers["Vary"] = "Accept-Encoding"
273273
end
274274

275275
headers
@@ -279,15 +279,15 @@ def headers(env, asset, length)
279279
headers = {}
280280

281281
# Set content length header
282-
headers["content-length"] = length.to_s
282+
headers["Content-Length"] = length.to_s
283283

284284
# Set content type header
285285
if type = asset.content_type
286286
# Set charset param for text/* mime types
287287
if type.start_with?("text/") && asset.charset
288288
type += "; charset=#{asset.charset}"
289289
end
290-
headers["content-type"] = type
290+
headers["Content-Type"] = type
291291
end
292292

293293
headers.merge(cache_headers(env, asset.etag))

test/test_server.rb

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ def app
3636
test "serve single source file" do
3737
get "/assets/foo.js"
3838
assert_equal 200, last_response.status
39-
assert_equal "9", last_response.headers['content-length']
40-
assert_equal "Accept-Encoding", last_response.headers['vary']
39+
assert_equal "9", last_response.headers['Content-Length']
40+
assert_equal "Accept-Encoding", last_response.headers['Vary']
4141
assert_equal "var foo;\n", last_response.body
4242
end
4343

4444
test "serve single self file" do
4545
get "/assets/foo.self.js"
4646
assert_equal 200, last_response.status
47-
assert_equal "9", last_response.headers['content-length']
47+
assert_equal "9", last_response.headers['Content-Length']
4848
assert_equal "var foo;\n", last_response.body
4949
end
5050

@@ -64,30 +64,30 @@ def app
6464
assert_equal 200, last_response.status
6565
assert_equal "\n(function() {\n application.boot();\n})();\n",
6666
last_response.body
67-
assert_equal "43", last_response.headers['content-length']
67+
assert_equal "43", last_response.headers['Content-Length']
6868
end
6969

7070
test "serve source with content type headers" do
7171
get "/assets/application.js"
72-
assert_equal "application/javascript", last_response.headers['content-type']
72+
assert_equal "application/javascript", last_response.headers['Content-Type']
7373

7474
get "/assets/bootstrap.css"
75-
assert_equal "text/css; charset=utf-8", last_response.headers['content-type']
75+
assert_equal "text/css; charset=utf-8", last_response.headers['Content-Type']
7676
end
7777

7878
test "serve source with etag headers" do
7979
digest = @env['application.js'].etag
8080

8181
get "/assets/application.js"
8282
assert_equal "\"#{digest}\"",
83-
last_response.headers['etag']
83+
last_response.headers['ETag']
8484
end
8585

8686
test "not modified partial response when if-none-match etags match" do
8787
get "/assets/application.js"
8888
assert_equal 200, last_response.status
8989
etag, cache_control, expires, vary = last_response.headers.values_at(
90-
'etag', 'cache-control', 'Expires', 'vary'
90+
'ETag', 'Cache-Control', 'Expires', 'Vary'
9191
)
9292

9393
assert_nil expires
@@ -97,14 +97,14 @@ def app
9797
assert_equal 304, last_response.status
9898

9999
# Allow 304 headers
100-
assert_equal cache_control, last_response.headers['cache-control']
101-
assert_equal etag, last_response.headers['etag']
100+
assert_equal cache_control, last_response.headers['Cache-Control']
101+
assert_equal etag, last_response.headers['ETag']
102102
assert_nil last_response.headers['Expires']
103-
assert_equal vary, last_response.headers['vary']
103+
assert_equal vary, last_response.headers['Vary']
104104

105105
# Disallowed 304 headers
106-
refute last_response.headers['content-type']
107-
refute last_response.headers['content-length']
106+
refute last_response.headers['Content-Type']
107+
refute last_response.headers['Content-Length']
108108
refute last_response.headers['Content-Encoding']
109109
end
110110

@@ -113,15 +113,15 @@ def app
113113
'HTTP_IF_NONE_MATCH' => "nope"
114114

115115
assert_equal 200, last_response.status
116-
assert_equal '"b452c9ae1d5c8d9246653e0d93bc83abce0ee09ef725c0f0a29a41269c217b83"', last_response.headers['etag']
117-
assert_equal '52', last_response.headers['content-length']
116+
assert_equal '"b452c9ae1d5c8d9246653e0d93bc83abce0ee09ef725c0f0a29a41269c217b83"', last_response.headers['ETag']
117+
assert_equal '52', last_response.headers['Content-Length']
118118
end
119119

120120
test "not modified partial response with fingerprint and if-none-match etags match" do
121121
get "/assets/application.js"
122122
assert_equal 200, last_response.status
123123

124-
etag = last_response.headers['etag']
124+
etag = last_response.headers['ETag']
125125
digest = etag[/"(.+)"/, 1]
126126

127127
get "/assets/application-#{digest}.js", {},
@@ -133,7 +133,7 @@ def app
133133
get "/assets/prehashed-988881adc9fc3655077dc2d4d757d480b5ea0e11.js"
134134
assert_equal 200, last_response.status
135135

136-
etag = last_response.headers['etag']
136+
etag = last_response.headers['ETag']
137137
digest = etag[/"(.+)"/, 1]
138138

139139
assert_equal 'edabfd0f1ac5fcdae82cc7d92d1c52abb671797a3948fa9040aec1db8e61c327', digest
@@ -153,7 +153,7 @@ def app
153153
get "/assets/application.js"
154154
assert_equal 200, last_response.status
155155

156-
etag = last_response.headers['etag']
156+
etag = last_response.headers['ETag']
157157
digest = etag[/"(.+)"/, 1]
158158

159159
get "/assets/application-#{digest}.js", {},
@@ -177,7 +177,7 @@ def app
177177
get "/assets/application.js"
178178
assert_equal 200, last_response.status
179179

180-
etag = last_response.headers['etag']
180+
etag = last_response.headers['ETag']
181181

182182
get "/assets/application-0000000000000000000000000000000000000000.js", {},
183183
'HTTP_IF_NONE_MATCH' => etag
@@ -187,22 +187,22 @@ def app
187187
test "ok partial response when if-match etags match" do
188188
get "/assets/application.js"
189189
assert_equal 200, last_response.status
190-
etag = last_response.headers['etag']
190+
etag = last_response.headers['ETag']
191191

192192
get "/assets/application.js", {},
193193
'HTTP_IF_MATCH' => etag
194194

195195
assert_equal 200, last_response.status
196-
assert_equal '"b452c9ae1d5c8d9246653e0d93bc83abce0ee09ef725c0f0a29a41269c217b83"', last_response.headers['etag']
197-
assert_equal '52', last_response.headers['content-length']
196+
assert_equal '"b452c9ae1d5c8d9246653e0d93bc83abce0ee09ef725c0f0a29a41269c217b83"', last_response.headers['ETag']
197+
assert_equal '52', last_response.headers['Content-Length']
198198
end
199199

200200
test "precondition failed with if-match is a mismatch" do
201201
get "/assets/application.js", {},
202202
'HTTP_IF_MATCH' => '"000"'
203203
assert_equal 412, last_response.status
204204

205-
refute last_response.headers['etag']
205+
refute last_response.headers['ETag']
206206
end
207207

208208
test "not found with if-match" do
@@ -225,23 +225,23 @@ def app
225225

226226
test "fingerprint digest sets expiration to the future" do
227227
get "/assets/application.js"
228-
digest = last_response.headers['etag'][/"(.+)"/, 1]
228+
digest = last_response.headers['ETag'][/"(.+)"/, 1]
229229

230230
get "/assets/application-#{digest}.js"
231231
assert_equal 200, last_response.status
232-
assert_match %r{max-age}, last_response.headers['cache-control']
233-
assert_match %r{immutable}, last_response.headers['cache-control']
232+
assert_match %r{max-age}, last_response.headers['Cache-Control']
233+
assert_match %r{immutable}, last_response.headers['Cache-Control']
234234
end
235235

236236
test "fingerprint digest of file self" do
237237
get "/assets/application.self.js"
238-
digest = last_response.headers['etag'][/"(.+)"/, 1]
238+
digest = last_response.headers['ETag'][/"(.+)"/, 1]
239239

240240
get "/assets/application.self-#{digest}.js"
241241
assert_equal 200, last_response.status
242242
assert_equal "\n(function() {\n application.boot();\n})();\n", last_response.body
243-
assert_equal "43", last_response.headers['content-length']
244-
assert_match %r{max-age}, last_response.headers['cache-control']
243+
assert_equal "43", last_response.headers['Content-Length']
244+
assert_match %r{max-age}, last_response.headers['Cache-Control']
245245
end
246246

247247
test "bad fingerprint digest returns a 404" do
@@ -250,14 +250,14 @@ def app
250250

251251
head "/assets/application-0000000000000000000000000000000000000000.js"
252252
assert_equal 404, last_response.status
253-
assert_equal "0", last_response.headers['content-length']
253+
assert_equal "0", last_response.headers['Content-Length']
254254
assert_equal "", last_response.body
255255
end
256256

257257
test "missing source" do
258258
get "/assets/none.js"
259259
assert_equal 404, last_response.status
260-
assert_equal "pass", last_response.headers['x-cascade']
260+
assert_equal "pass", last_response.headers['X-Cascade']
261261
end
262262

263263
test "re-throw JS exceptions in the browser" do
@@ -302,7 +302,7 @@ def app
302302

303303
head "/assets/.-0000000./etc/passwd"
304304
assert_equal 403, last_response.status
305-
assert_equal "0", last_response.headers['content-length']
305+
assert_equal "0", last_response.headers['Content-Length']
306306
assert_equal "", last_response.body
307307
end
308308

@@ -336,7 +336,7 @@ def app
336336
test "serving static assets" do
337337
get "/assets/logo.png"
338338
assert_equal 200, last_response.status
339-
assert_equal "image/png", last_response.headers['content-type']
339+
assert_equal "image/png", last_response.headers['Content-Type']
340340
refute last_response.headers['Content-Encoding']
341341
assert_equal File.binread(fixture_path("server/app/images/logo.png")), last_response.body
342342
end
@@ -347,8 +347,8 @@ def app
347347

348348
head "/assets/foo.js"
349349
assert_equal 200, last_response.status
350-
assert_equal "application/javascript", last_response.headers['content-type']
351-
assert_equal "0", last_response.headers['content-length']
350+
assert_equal "application/javascript", last_response.headers['Content-Type']
351+
assert_equal "0", last_response.headers['Content-Length']
352352
assert_equal "", last_response.body
353353

354354
post "/assets/foo.js"

0 commit comments

Comments
 (0)