class Responder

Negotiates response content types and invokes the matching handler.

Classes and Modules

class Handler < Struct

A content-type handler and its response block.

Definitions

def initialize(handlers = Protocol::Media::Map.new, passthrough = nil)

Initialize a responder with a handler map.

Signature

parameter handlers Protocol::Media::Map

The response handlers.

parameter passthrough Object | Nil

The fallback response handler.

Implementation

def initialize(handlers = Protocol::Media::Map.new, passthrough = nil)
	@handlers = handlers
	@passthrough = passthrough
end

def freeze

Freeze this responder and compile its handler map.

Signature

returns self

This responder.

Implementation

def freeze
	return self if frozen?
	
	@handlers.freeze
	
	return super
end

def handle(content_type, &block)

Add a serializer for the specified content type.

Signature

parameter content_type String | Protocol::Media::Type

The produced media type.

returns self

This responder.

Implementation

def handle(content_type, &block)
	@handlers[content_type] = Handler.new(content_type, block).freeze
	return self
end

def with_json

Register the default JSON handler.

Signature

returns self

This responder.

Implementation

def with_json
	@handlers[Handlers::JSON::APPLICATION_JSON] = Handlers::JSON
	return self
end

def with_passthrough

Register the wildcard passthrough handler.

Signature

returns self

This responder.

Implementation

def with_passthrough
	@passthrough = Handlers::Passthrough
	return self
end

def with(content_type, &block)

Add a serializer for the specified content type.

Signature

parameter content_type String | Protocol::Media::Type

The produced media type.

returns self

This responder.

Implementation

def with(content_type, &block)
	return handle(content_type, &block)
end

def call(context, request, *arguments, **options)

Negotiate the request's accepted media types and invoke the best handler.

Signature

parameter context Object

The controller context.

parameter request Utopia::Request

The request.

parameter arguments Array

The arguments.

parameter options Hash

The options.

returns Array(Object, Object) | Nil

The selected content type and body, or nil if none matches.

Implementation

def call(context, request, *arguments, **options)
	accept = request.headers["accept"]
	
	# An absent or empty Accept header accepts any media type:
	if accept.nil? || accept.empty?
		media_ranges = [Handlers::Passthrough::WILDCARD]
	else
		media_ranges = accept.preferred_media_ranges
	end
	
	if match = @handlers.for(media_ranges)
		handler, media_range = match
	elsif @passthrough
		handler = @passthrough
		media_range = media_ranges.first
	end
	
	if handler
		return handler.content_type, handler.call(context, request, media_range, *arguments, **options)
	end
	
	return nil
end