55
66require_relative "middleware"
77
8+ require "protocol/http/header/accept"
9+ require "protocol/media/map"
10+ require "protocol/media/type"
11+ require "protocol/media/range"
12+
813module Utopia
914 module Controller
1015 # @namespace
1116 module Handlers
1217 # Serializes controller values as JSON responses.
1318 module JSON
14- APPLICATION_JSON = HTTP ::Accept ::ContentType . new ( "application" , "json" ) . freeze
15-
16- # Delegate content-type splitting to the JSON media type.
17- # @parameter arguments [Array] The arguments.
18- # @returns [Array] The resulting values.
19- def self . split ( *arguments )
20- APPLICATION_JSON . split ( *arguments )
21- end
19+ APPLICATION_JSON = Protocol ::Media ::Type . new ( "application" , "json" ) . freeze
2220
2321 # Serialize an object as a successful JSON response.
2422 # @parameter context [Object] The context.
2523 # @parameter request [Utopia::Request] The request.
26- # @parameter media_range [HTTP::Accept::MediaTypes ::MediaRange] The negotiated media range.
24+ # @parameter media_range [Protocol:: HTTP::Header::Accept ::MediaRange] The negotiated media range.
2725 # @parameter object [Object] The object.
2826 # @parameter options [Hash] The options.
2927 # @returns [Object] The result of {Controller::Base#succeed!}.
@@ -38,19 +36,12 @@ def self.call(context, request, media_range, object, **options)
3836
3937 # Passes response values through without transformation.
4038 module Passthrough
41- WILDCARD = HTTP ::Accept ::MediaTypes ::MediaRange . new ( "*" , "*" ) . freeze
42-
43- # Delegate content-type splitting to the wildcard media range.
44- # @parameter arguments [Array] The arguments.
45- # @returns [Array] The resulting values.
46- def self . split ( *arguments )
47- WILDCARD . split ( *arguments )
48- end
39+ WILDCARD = Protocol ::Media ::Range . new ( "*" , "*" ) . freeze
4940
5041 # Accept an object without producing a response.
5142 # @parameter context [Object] The context.
5243 # @parameter request [Utopia::Request] The request.
53- # @parameter media_range [HTTP::Accept::MediaTypes ::MediaRange] The negotiated media range.
44+ # @parameter media_range [Protocol:: HTTP::Header::Accept ::MediaRange] The negotiated media range.
5445 # @parameter object [Object] The object.
5546 # @parameter options [Hash] The options.
5647 # @returns [Nil] No response is produced.
@@ -64,17 +55,10 @@ def self.call(context, request, media_range, object, **options)
6455 class Responder
6556 # A content-type handler and its response block.
6657 Handler = Struct . new ( :content_type , :block ) do
67- # Delegate content-type splitting to this handler's content type.
68- # @parameter arguments [Array] The arguments.
69- # @returns [Array] The resulting values.
70- def split ( *arguments )
71- self . content_type . split ( *arguments )
72- end
73-
7458 # Invoke this handler's block in the controller context.
7559 # @parameter context [Object] The context.
7660 # @parameter request [Utopia::Request] The request.
77- # @parameter media_range [HTTP::Accept::MediaTypes ::MediaRange] The negotiated media range.
61+ # @parameter media_range [Protocol:: HTTP::Header::Accept ::MediaRange] The negotiated media range.
7862 # @parameter arguments [Array] The arguments.
7963 # @parameter options [Hash] The options.
8064 # @returns [Object] The handler block's result.
@@ -93,7 +77,7 @@ def with(object, **options)
9377
9478 # Initialize an empty content-type handler map.
9579 def initialize
96- @handlers = HTTP :: Accept :: MediaTypes ::Map . new
80+ @handlers = Protocol :: Media ::Map . new
9781 end
9882
9983 attr :handlers
@@ -113,10 +97,11 @@ def freeze
11397 # @parameter options [Hash] The options.
11498 # @returns [Object | Nil] The selected handler's result, or `nil` if none matches.
11599 def call ( context , request , *arguments , **options )
116- # Parse the list of browser preferred content types and return ordered by priority:
117- media_types = HTTP ::Accept ::MediaTypes . browser_preferred_media_types (
118- HTTP ::Accept ::MediaTypes ::HTTP_ACCEPT => Array ( request . headers [ "accept" ] ) . join ( "," )
119- )
100+ if accept = request . headers [ "accept" ]
101+ media_types = accept . media_ranges . sort
102+ else
103+ media_types = [ Handlers ::Passthrough ::WILDCARD ]
104+ end
120105
121106 handler , media_range = @handlers . for ( media_types )
122107
@@ -127,7 +112,8 @@ def call(context, request, *arguments, **options)
127112
128113 # Add a converter for the specified content type. Call the block with the response content if the request accepts the specified content_type.
129114 def handle ( content_type , &block )
130- @handlers << Handler . new ( content_type , block )
115+ @handlers [ content_type ] = Handler . new ( content_type , block )
116+ return @handlers
131117 end
132118
133119 # Bind this responder to a context and request.
@@ -139,21 +125,23 @@ def respond_to(context, request)
139125 end
140126
141127 # Register the default JSON handler.
142- # @returns [HTTP::Accept::MediaTypes ::Map] The updated handler map.
128+ # @returns [Protocol::Media ::Map] The updated handler map.
143129 def with_json
144- @handlers << Handlers ::JSON
130+ @handlers [ Handlers ::JSON ::APPLICATION_JSON ] = Handlers ::JSON
131+ return @handlers
145132 end
146133
147134 # Register the wildcard passthrough handler.
148- # @returns [HTTP::Accept::MediaTypes ::Map] The updated handler map.
135+ # @returns [Protocol::Media ::Map] The updated handler map.
149136 def with_passthrough
150- @handlers << Handlers ::Passthrough
137+ @handlers [ Handlers ::Passthrough ::WILDCARD ] = Handlers ::Passthrough
138+ return @handlers
151139 end
152140
153141 # Invoke the responder with the given object.
154142 # @parameter content_type [String] The content type.
155143 # @yields The response handler body.
156- # @returns [HTTP::Accept::MediaTypes ::Map] The updated handler map.
144+ # @returns [Protocol::Media ::Map] The updated handler map.
157145 def with ( content_type , &block )
158146 handle ( content_type , &block )
159147 end
0 commit comments