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
	]
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, **options) ⇒ Static

Returns a new instance of Static.



207
208
209
210
211
212
213
214
215
216
# File 'lib/utopia/static.rb', line 207

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] || "public, max-age=3600")
	
	self.freeze
end

Instance Attribute Details

#extensions ⇒ Object (readonly)

Returns the value of attribute extensions.



237
238
239
# File 'lib/utopia/static.rb', line 237

def extensions
  @extensions
end

Instance Method Details

#call(env) ⇒ Object



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/utopia/static.rb', line 239

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



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

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

#freeze ⇒ Object



218
219
220
221
222
223
224
# File 'lib/utopia/static.rb', line 218

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