Class: Rack::SmartCompress::Static

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/smart_compress/static.rb

Defined Under Namespace

Classes: FileBody

Constant Summary collapse

DEFAULT_EXTENSIONS =
{
  "zstd" => ".zst",
  "br"   => ".br",
  "gzip" => ".gz"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Static

Returns a new instance of Static.



38
39
40
41
42
43
44
45
# File 'lib/rack/smart_compress/static.rb', line 38

def initialize(app, options = {})
  @app = app
  @root = File.expand_path(options.fetch(:root, "public"))
  @urls = Array(options.fetch(:urls, ["/"])).map(&:to_s)
  @encodings = options.fetch(:encodings, DEFAULT_EXTENSIONS)
  @headers = options.fetch(:headers, {})
  @cascade = options.fetch(:cascade, true)
end

Instance Attribute Details

#appObject (readonly)

Returns the value of attribute app.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def app
  @app
end

#cascadeObject (readonly)

Returns the value of attribute cascade.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def cascade
  @cascade
end

#encodingsObject (readonly)

Returns the value of attribute encodings.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def encodings
  @encodings
end

#headersObject (readonly)

Returns the value of attribute headers.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def headers
  @headers
end

#rootObject (readonly)

Returns the value of attribute root.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def root
  @root
end

#urlsObject (readonly)

Returns the value of attribute urls.



36
37
38
# File 'lib/rack/smart_compress/static.rb', line 36

def urls
  @urls
end

Instance Method Details

#call(env) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rack/smart_compress/static.rb', line 47

def call(env)
  method = env["REQUEST_METHOD"]
  return @app.call(env) unless %w[GET HEAD].include?(method)

  path_info = env["PATH_INFO"].to_s
  return @app.call(env) unless url_match?(path_info)

  clean_path = Rack::Utils.clean_path_info(path_info)
  full_path = File.join(@root, clean_path)

  # Path traversal guard: ensure path is strictly inside @root
  return @app.call(env) unless safe_path?(full_path)

  accept_encoding = env["HTTP_ACCEPT_ENCODING"].to_s
  encoding, compressed_path = find_precompressed_file(full_path, accept_encoding)

  if compressed_path
    serve_file(env, full_path, compressed_path, encoding, method)
  elsif File.file?(full_path) && !@cascade
    serve_file(env, full_path, full_path, nil, method)
  else
    @app.call(env)
  end
end