Class: Utopia::Static

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

Overview

A middleware which serves static files from the specified root directory.

Defined Under Namespace

Classes: LocalFile, MimeTypeLoader

Constant Summary collapse

MIME_TYPES =

Default mime-types which are common for files served over HTTP:

{
	: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, root: Utopia::default_root, types: , cache_control: DEFAULT_CACHE_CONTROL) ⇒ Static

Returns a new instance of Static.

Parameters:

  • root (String) (defaults to: Utopia::default_root)

    The root directory to serve files from.

  • types (Array) (defaults to: )

    The mime-types (and file extensions) to recognize/serve.

  • cache_control (String) (defaults to: DEFAULT_CACHE_CONTROL)

    The cache-control header to set for static content.



225
226
227
228
229
230
231
232
# File 'lib/utopia/static.rb', line 225

def initialize(app, root: Utopia::default_root, types: MIME_TYPES[:default], cache_control: DEFAULT_CACHE_CONTROL)
	@app = app
	@root = root
	
	@extensions = MimeTypeLoader.extensions_for(types)
	
	@cache_control = cache_control
end

Instance Attribute Details

#extensionsObject (readonly)

Returns the value of attribute extensions.



255
256
257
# File 'lib/utopia/static.rb', line 255

def extensions
  @extensions
end

Instance Method Details

#call(env) ⇒ Object



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
288
289
290
291
292
293
# File 'lib/utopia/static.rb', line 263

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



244
245
246
247
248
249
250
251
252
253
# File 'lib/utopia/static.rb', line 244

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



234
235
236
237
238
239
240
241
242
# File 'lib/utopia/static.rb', line 234

def freeze
	return self if frozen?
	
	@root.freeze
	@extensions.freeze
	@cache_control.freeze
	
	super
end