class Rack::Brotli::Deflater
This middleware enables compression of http responses.
Currently supported compression algorithms:
* br
The middleware automatically detects when compression is supported and allowed. For example no transformation is made when a cache directive of 'no-transform' is present, or when the response status code is one that doesn't allow an entity body.
Public Class Methods
new(app, options = {})
click to toggle source
Creates Rack::Brotli
middleware.
- app
-
rack app instance
- options
-
hash of deflater options, i.e. 'if' - a lambda enabling / disabling deflation based on returned boolean value
e.g use Rack::Brotli, :if => lambda { |env, status, headers, body| body.map(&:bytesize).reduce(0, :+) > 512 }
'include' - a list of content types that should be compressed 'deflater' -
Brotli
compression options
# File lib/rack/brotli/deflater.rb 25 def initialize(app, options = {}) 26 @app = app 27 28 @condition = options[:if] 29 @compressible_types = options[:include] 30 @deflater_options = { quality: 5 }.merge(options[:deflater] || {}) 31 end
Public Instance Methods
call(env)
click to toggle source
# File lib/rack/brotli/deflater.rb 33 def call(env) 34 status, headers, body = @app.call(env) 35 headers = Rack::Utils::HeaderHash.new(headers) 36 37 unless should_deflate?(env, status, headers, body) 38 return [status, headers, body] 39 end 40 41 request = Rack::Request.new(env) 42 43 encoding = Rack::Utils.select_best_encoding(%w(br), 44 request.accept_encoding) 45 46 return [status, headers, body] unless encoding 47 48 # Set the Vary HTTP header. 49 vary = headers["Vary"].to_s.split(",").map(&:strip) 50 unless vary.include?("*") || vary.include?("Accept-Encoding") 51 headers["Vary"] = vary.push("Accept-Encoding").join(",") 52 end 53 54 case encoding 55 when "br" 56 headers['Content-Encoding'] = "br" 57 headers.delete(Rack::CONTENT_LENGTH) 58 [status, headers, BrotliStream.new(body, @deflater_options)] 59 when nil 60 message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found." 61 bp = Rack::BodyProxy.new([message]) { body.close if body.respond_to?(:close) } 62 [406, {Rack::CONTENT_TYPE => "text/plain", Rack::CONTENT_LENGTH => message.length.to_s}, bp] 63 end 64 end
Private Instance Methods
should_deflate?(env, status, headers, body)
click to toggle source
# File lib/rack/brotli/deflater.rb 93 def should_deflate?(env, status, headers, body) 94 # Skip compressing empty entity body responses and responses with 95 # no-transform set. 96 if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) || 97 headers[Rack::CACHE_CONTROL].to_s =~ /\bno-transform\b/ || 98 (headers['Content-Encoding'] && headers['Content-Encoding'] !~ /\bidentity\b/) 99 return false 100 end 101 102 # Skip if @compressible_types are given and does not include request's content type 103 return false if @compressible_types && !(headers.has_key?(Rack::CONTENT_TYPE) && @compressible_types.include?(headers[Rack::CONTENT_TYPE][/[^;]*/])) 104 105 # Skip if @condition lambda is given and evaluates to false 106 return false if @condition && !@condition.call(env, status, headers, body) 107 108 true 109 end