Class: Utopia::Static

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

Overview

Serve static files and include recursive name resolution using @rel@ directory entries.

Defined Under Namespace

Classes: LocalFile, MimeTypeLoader

Constant Summary collapse

MIME_TYPES =
{
  :xiph => {
    "ogx" => "application/ogg",
    "ogv" => "video/ogg",
    "oga" => "audio/ogg",
    "ogg" => "audio/ogg",
    "spx" => "audio/ogg",
    "flac" => "audio/flac",
    "anx" => "application/annodex",
    "axa" => "audio/annodex",
    "xspf" => "application/xspf+xml",
  },
  :media => [
    :xiph, "mp3", "mp4", "wav", "aiff", ["aac", "audio/x-aac"], "mov", "avi", "wmv", "mpg"
  ],
  :text => [
    "html", "css", "js", ["map", "application/json"], "txt", "rtf", "xml", "pdf"
  ],
  :fonts => [
    "otf", ["eot", "application/vnd.ms-fontobject"], "ttf", "woff"
  ],
  :archive => [
    "zip", "tar", "tgz", "tar.gz", "tar.bz2", ["dmg", "application/x-apple-diskimage"],
    ["torrent", "application/x-bittorrent"]
  ],
  :images => [
    "png", "gif", "jpeg", "tiff", "svg"
  ],
  :default => [
    :media, :text, :archive, :images, :fonts
  ]
}
DEFAULT_CACHE_CONTROL =
'public, max-age=3600'.freeze
LAST_MODIFIED =
'Last-Modified'.freeze
CONTENT_TYPE =
HTTP::CONTENT_TYPE
CACHE_CONTROL =
HTTP::CACHE_CONTROL
ETAG =
'ETag'.freeze
ACCEPT_RANGES =
'Accept-Ranges'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, **options) ⇒ Static

Returns a new instance of Static.



219
220
221
222
223
224
225
226
227
228
# File 'lib/utopia/static.rb', line 219

def initialize(app, **options)
  @app = app
  @root = (options[:root] || Utopia::default_root).freeze

  @extensions = MimeTypeLoader.extensions_for(options[:types] || MIME_TYPES[:default])

  @cache_control = (options[:cache_control] || DEFAULT_CACHE_CONTROL)
  
  self.freeze
end

Instance Attribute Details

#extensionsObject (readonly)

Returns the value of attribute extensions.



249
250
251
# File 'lib/utopia/static.rb', line 249

def extensions
  @extensions
end

Instance Method Details

#call(env) ⇒ Object



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/utopia/static.rb', line 257

def call(env)
  path_info = env[Rack::PATH_INFO]
  extension = File.extname(path_info)

  if @extensions.key? extension.downcase
    path = Path[path_info].simplify
    
    if locale = env[Localization::CURRENT_LOCALE_KEY]
      path.last.insert(path.last.rindex('.') || -1, ".#{locale}")
    end
    
    if file = fetch_file(path)
      response_headers = {
        LAST_MODIFIED => file.mtime_date,
        CONTENT_TYPE => @extensions[extension],
        CACHE_CONTROL => @cache_control,
        ETAG => file.etag,
        ACCEPT_RANGES => "bytes"
      }

      if file.modified?(env)
        return file.serve(env, response_headers)
      else
        return [304, response_headers, []]
      end
    end
  end

  # else if no file was found:
  return @app.call(env)
end

#fetch_file(path) ⇒ Object



238
239
240
241
242
243
244
245
246
247
# File 'lib/utopia/static.rb', line 238

def fetch_file(path)
  # We need file_path to be an absolute path for X-Sendfile to work correctly.
  file_path = File.join(@root, path.components)
  
  if File.exist?(file_path)
    return LocalFile.new(@root, path)
  else
    return nil
  end
end

#freezeObject



230
231
232
233
234
235
236
# File 'lib/utopia/static.rb', line 230

def freeze
  @root.freeze
  @extensions.freeze
  @cache_control.freeze
  
  super
end