提交 90006acb 编写于 作者: G Guillermo Iguaran

Merge pull request #16466 from schneems/schneems/gzip-action-dispatch

Enable gzip compression by default
* Requests that hit `ActionDispatch::Static` can now take advantage
of gzipped assets on disk. By default a gzip asset will be served if
the client supports gzip and a compressed file is on disk.
*Richard Schneeman*
* `ActionController::Parameters` will stop inheriting from `Hash` and
`HashWithIndifferentAccess` in the next major release. If you use any method
that is not available on `ActionController::Parameters` you should consider
......
......@@ -16,8 +16,9 @@ class FileHandler
def initialize(root, cache_control)
@root = root.chomp('/')
@compiled_root = /^#{Regexp.escape(root)}/
headers = cache_control && { 'Cache-Control' => cache_control }
@file_server = ::Rack::File.new(@root, headers)
headers = {}
headers['Cache-Control'] = cache_control if cache_control
@file_server = ::Rack::File.new(@root, headers)
end
def match?(path)
......@@ -36,23 +37,48 @@ def match?(path)
end
def call(env)
@file_server.call(env)
path = env['PATH_INFO']
gzip_file_exists = gzip_file_exists?(path)
if gzip_file_exists && gzip_encoding_accepted?(env)
env['PATH_INFO'] = "#{path}.gz"
status, headers, body = @file_server.call(env)
headers['Content-Encoding'] = 'gzip'
headers['Content-Type'] = content_type(path)
else
status, headers, body = @file_server.call(env)
end
headers['Vary'] = 'Accept-Encoding' if gzip_file_exists
return [status, headers, body]
end
def ext
@ext ||= begin
ext = ::ActionController::Base.default_static_extension
"{,#{ext},/index#{ext}}"
private
def ext
@ext ||= begin
ext = ::ActionController::Base.default_static_extension
"{,#{ext},/index#{ext}}"
end
end
end
def unescape_path(path)
URI.parser.unescape(path)
end
def unescape_path(path)
URI.parser.unescape(path)
end
def escape_glob_chars(path)
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
end
def escape_glob_chars(path)
path.gsub(/[*?{}\[\]]/, "\\\\\\&")
end
def content_type(path)
::Rack::Mime.mime_type(::File.extname(path), 'text/plain')
end
def gzip_encoding_accepted?(env)
env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
end
def gzip_file_exists?(path)
File.exist?(File.join(@root, "#{::Rack::Utils.unescape(path)}.gz"))
end
end
# This middleware will attempt to return the contents of a file's body from
......
# encoding: utf-8
require 'abstract_unit'
require 'rbconfig'
require 'zlib'
module StaticTests
def test_serves_dynamic_content
......@@ -106,6 +107,18 @@ def test_serves_static_file_with_at_symbol_in_filename
end
end
def test_serves_gzip_files_when_header_set
file_name = "/gzip/application-a71b3024f80aea3181c09774ca17e712.js"
response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip')
assert_gzip file_name, response
assert_equal 'application/javascript', response.headers['Content-Type']
assert_equal 'Accept-Encoding', response.headers["Vary"]
assert_equal 'gzip', response.headers["Content-Encoding"]
response = get(file_name, 'HTTP_ACCEPT_ENCODING' => '')
refute_equal 'gzip', response.headers["Content-Encoding"]
end
# Windows doesn't allow \ / : * ? " < > | in filenames
unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
def test_serves_static_file_with_colon
......@@ -125,13 +138,20 @@ def test_serves_static_file_with_asterisk
private
def assert_gzip(file_name, response)
expected = File.read("#{FIXTURE_LOAD_PATH}/#{public_path}" + file_name)
actual = Zlib::GzipReader.new(StringIO.new(response.body)).read
assert_equal expected, actual
end
def assert_html(body, response)
assert_equal body, response.body
assert_equal "text/html", response.headers["Content-Type"]
refute response.headers.key?("Vary")
end
def get(path)
Rack::MockRequest.new(@app).request("GET", path)
def get(path, headers = {})
Rack::MockRequest.new(@app).request("GET", path, headers)
end
def with_static_file(file)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册