class Middleware < Protocol::HTTP::Middleware

Inherits from
Protocol::HTTP::Middleware
Includes
Localization::Resolver

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

Definitions

def initialize(app, root: Utopia::default_root, types: MIME_TYPES[:default], cache_control: DEFAULT_CACHE_CONTROL)

Implementation

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

def freeze

Freeze this object and its internal state.

Signature

returns self

This object.

Implementation

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

def response_headers_for(file, content_type)

Build response headers for the given file.

Signature

parameter file LocalFile

The file.

parameter content_type String

The content type.

returns Hash(String, String)

The response headers.

Implementation

def response_headers_for(file, content_type)
	if @cache_control.respond_to?(:call)
		cache_control = @cache_control.call(file)
	else
		cache_control = @cache_control
	end
	
	{
		LAST_MODIFIED => file.mtime_date,
		CONTENT_TYPE => content_type,
		CACHE_CONTROL => cache_control,
		ETAG => file.etag,
		ACCEPT_RANGES => "bytes"
	}
end

def respond(request, path, extension, content_type, localization: request.localization)

Respond.

Signature

parameter request Utopia::Request

The request.

parameter path Protocol::URL::Path

The request path to serve.

parameter extension String

The file extension.

parameter content_type String

The file media type.

parameter localization Utopia::Localization::Preferences | Nil

The selected localization.

returns Protocol::HTTP::Response

The response.

Implementation

def respond(request, path, extension, content_type, localization: request.localization)
	local_path = path.local_path(@root)
	
	if locale = localization&.locale
		local_path = local_path.delete_suffix(extension) + ".#{locale}#{extension}"
	end
	
	if file = fetch_file(local_path)
		response_headers = self.response_headers_for(file, content_type)
		
		if file.modified?(request)
			return file.serve(request, response_headers)
		else
			return Response[304, response_headers, []]
		end
	end
end

def call(request)

Serve a recognized static file or pass the request to the next middleware.

Signature

parameter request Utopia::Request

The request.

returns Protocol::HTTP::Response

The static-file or downstream response.

Implementation

def call(request)
	case request.method
	when Protocol::HTTP::Methods::GET, Protocol::HTTP::Methods::HEAD
	else
		return @delegate.call(request)
	end
	
	path = request.url.path
	extension = File.extname(path.basename)
	
	if content_type = @extensions[extension.downcase]
		response = resolve_localized(request) do |localization|
			self.respond(request, path, extension, content_type, localization: localization)
		end
		
		if response
			return response
		end
	end
	
	# else if no file was found:
	return @delegate.call(request)
end