Module: Strelka::HTTPResponse::Negotiation
- Extended by:
- MethodUtilities
- Includes:
- Constants
- Defined in:
- lib/strelka/httpresponse/negotiation.rb
Overview
The mixin that adds methods to Strelka::HTTPResponse for content-negotiation.
response = request.response
response.for( 'text/html' ) {...}
response.for( :json ) {...}
response.for_encoding( :en ) {...}
response.for_language( :en ) {...}
If the response was created from a request, it also knows whether or not it
is acceptable according to its request's Accept* headers.
Constant Summary collapse
- BUILTIN_MIMETYPE_MAP =
TODO: Perhaps replace this with something like this:
Mongrel2::Config::Mimetype.to_hash( :extension => :mimetype ) { :html => 'text/html', :text => 'text/plain', :yaml => 'application/x-yaml', :json => 'application/json', :jpeg => 'image/jpeg', :png => 'image/png', :gif => 'image/gif', :rdf => 'application/rdf+xml', :rss => 'application/rss+xml', :atom => 'application/atom+xml', }
- BUILTIN_STRINGIFIERS =
A collection of default stringifier callbacks, keyed by mimetype. If an entry for the content-negotiation callback's mimetype exists in this Hash, it will be #call()ed on the callback's return value to stringify the body.
{ 'application/x-yaml' => YAML.method( :dump ), 'application/json' => Yajl.method( :dump ), 'text/plain' => Proc.new {|obj| obj.to_s }, }
- UNICODE_CHARSETS =
Transcoding to Unicode is likely enough to work to warrant auto-transcoding. These are the charsets that will be used for auto-transcoding in the case where the whole entity body isn't in memory
[ Encoding::UTF_8, Encoding::UTF_16BE, Encoding::UTF_32BE, ]
Instance Attribute Summary collapse
-
#encoding_callbacks ⇒ Object
readonly
The Hash of document coding alternative callbacks for content negotiation, keyed by coding name.
-
#language_callbacks ⇒ Object
readonly
The Hash of language alternative callbacks for content negotiation, keyed by language tag String.
-
#mediatype_callbacks ⇒ Object
readonly
The Hash of mediatype alternative callbacks for content negotiation, keyed by mimetype.
-
#vary_fields ⇒ Object
readonly
A Set of header fields to add to the 'Vary:' response header.
Instance Method Summary collapse
-
#acceptable? ⇒ Boolean
(also: #is_acceptable?)
Return true if the receiver satisfies all of its originating request's Accept* headers, or it's a bodiless response.
-
#acceptable_charset? ⇒ Boolean
(also: #has_acceptable_charset?)
Returns true if the receiver's #charset is set to a value that was designated as acceptable by the originating request, or if there was no originating request.
-
#acceptable_content_type? ⇒ Boolean
(also: #has_acceptable_content_type?)
Returns true if the content-type of the response is set to a mediatype that was designated as acceptable by the originating request, or if there was no originating request.
-
#acceptable_encoding? ⇒ Boolean
(also: #has_acceptable_encoding?)
Returns true if all of the receiver's #encodings were designated as acceptable by the originating request, if there was no originating request, or if no #encodings have been set.
-
#acceptable_language? ⇒ Boolean
(also: #has_acceptable_language?)
Returns true if at least one of the receiver's #languages is set to a value that was designated as acceptable by the originating request, if there was no originating request, or if no #languages have been set for a non-empty entity body.
-
#better_charsets ⇒ Object
Returns Strelka::HTTPRequest::Charset objects for accepted character sets that have a higher qvalue than the one used by the current response.
-
#better_encoding ⇒ Object
Returns Strelka::HTTPRequest::Encoding objects for accepted encodings that have a higher qvalue than the one used by the current response.
-
#better_languages ⇒ Object
Returns Strelka::HTTPRequest::Language objects for natural languages that have a higher qvalue than the current response's entity body (if any).
-
#better_mediatypes ⇒ Object
Returns Strelka::HTTPRequest::MediaType objects for mediatypes that have a higher qvalue than the current response's entity body (if any).
-
#for(*mediatypes, &callback) ⇒ Object
Register a callback that will be called during transparent content negotiation for the entity body if one or more of the specified
mediatypesis among the requested alternatives. -
#for_encoding(*codings, &callback) ⇒ Object
Register a callback that will be called during transparent content negotiation for the entity body if one or more of the specified
codingsis among the requested alternatives. -
#for_language(*language_tags, &callback) ⇒ Object
Register a callback that will be called during transparent content negotiation for the entity body if one or more of the specified
language_tagsis among the requested alternatives. -
#initialize ⇒ Object
Add some instance variables for negotiation.
-
#mimetype_map ⇒ Object
The Hash of symbolic mediatypes of the form: { <name (Symbol)> =>
}. -
#negotiate ⇒ Object
Check for any negotiation that should happen and apply the necessary transforms if they're available.
-
#negotiated_body ⇒ Object
Transform the entity body if it doesn't meet the criteria.
-
#normalized_headers ⇒ Object
Overridden to add a Vary: header to outgoing headers if the response has any #vary_fields.
-
#reset ⇒ Object
Overridden to reset content-negotiation callbacks, too.
-
#stringifiers ⇒ Object
The Hash of stringification callbacks, keyed by mimetype.
-
#to_s ⇒ Object
Stringify the response -- overridden to use the negotiated body.
-
#transcode_body(charset) ⇒ Object
Try to transcode the entity body stream to one of the specified
charsets. -
#transform_charset ⇒ Object
Iterate over the originating request's acceptable charsets in qvalue+listed order, attempting to transcode the current entity body if it.
-
#transform_content_type ⇒ Object
Iterate over the originating request's acceptable content types in qvalue+listed order, looking for a content negotiation callback for each mediatype.
-
#transform_encoding ⇒ Object
Iterate over the originating request's acceptable encodings and apply each one in the order they were requested if they're available.
-
#transform_language ⇒ Object
If there are any languages that have a higher qvalue than the one/s in #languages, look for a negotiation callback that provides that language.
-
#try_content_type_callback(mimetype, callback) ⇒ Object
Attempt to apply the
callbackfor the specifiedmediatypeto the entity body, making the necessary changes to the request and returningtrueif the callback returns a new entity body, or returning a false value if it doesn't.
Methods included from MethodUtilities
attr_predicate, attr_predicate_accessor, singleton_attr_accessor, singleton_attr_reader, singleton_attr_writer, singleton_method_alias, singleton_predicate_accessor, singleton_predicate_reader
Instance Attribute Details
#encoding_callbacks ⇒ Object (readonly)
The Hash of document coding alternative callbacks for content negotiation, keyed by coding name.
105 106 107 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 105 def encoding_callbacks @encoding_callbacks end |
#language_callbacks ⇒ Object (readonly)
The Hash of language alternative callbacks for content negotiation, keyed by language tag String.
101 102 103 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 101 def language_callbacks @language_callbacks end |
#mediatype_callbacks ⇒ Object (readonly)
The Hash of mediatype alternative callbacks for content negotiation, keyed by mimetype.
97 98 99 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 97 def mediatype_callbacks @mediatype_callbacks end |
#vary_fields ⇒ Object (readonly)
A Set of header fields to add to the 'Vary:' response header.
108 109 110 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 108 def vary_fields @vary_fields end |
Instance Method Details
#acceptable? ⇒ Boolean Also known as: is_acceptable?
Return true if the receiver satisfies all of its originating request's Accept* headers, or it's a bodiless response.
171 172 173 174 175 176 177 178 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 171 def acceptable? # self.negotiate return self.bodiless? || ( self.acceptable_content_type? && self.acceptable_charset? && self.acceptable_language? && self.acceptable_encoding? ) end |
#acceptable_charset? ⇒ Boolean Also known as: has_acceptable_charset?
Returns true if the receiver's #charset is set to a value that was designated as acceptable by the originating request, or if there was no originating request.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 199 def acceptable_charset? req = self.request or return true charset = self.find_header_charset # Types other than text are binary, and so aren't subject to charset # acceptability. # For 'text/' subtypes: # When no explicit charset parameter is provided by the sender, media # subtypes of the "text" type are defined to have a default charset # value of "ISO-8859-1" when received via HTTP. [RFC2616 3.7.1] if charset == Encoding::ASCII_8BIT return true unless self.content_type.start_with?( 'text/' ) charset = Encoding::ISO8859_1 end answer = req.accepts_charset?( charset ) self.log.warn "Content-charset %p NOT acceptable: %p" % [ self.find_header_charset, req.accepted_charsets ] unless answer return answer end |
#acceptable_content_type? ⇒ Boolean Also known as: has_acceptable_content_type?
Returns true if the content-type of the response is set to a mediatype that was designated as acceptable by the originating request, or if there was no originating request.
185 186 187 188 189 190 191 192 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 185 def acceptable_content_type? req = self.request or return true answer = req.accepts?( self.content_type ) self.log.warn "Content-type %p NOT acceptable: %p" % [ self.content_type, req.accepted_mediatypes ] unless answer return answer end |
#acceptable_encoding? ⇒ Boolean Also known as: has_acceptable_encoding?
Returns true if all of the receiver's #encodings were designated as acceptable by the originating request, if there was no originating request, or if no #encodings have been set.
252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 252 def acceptable_encoding? req = self.request or return true encs = self.encodings.dup encs << 'identity' if encs.empty? answer = encs.all? {|enc| req.accepts_encoding?(enc) } self.log.warn "Content-encoding %p NOT acceptable: %s" % [ encs, req.accepted_encodings ] unless answer return answer end |
#acceptable_language? ⇒ Boolean Also known as: has_acceptable_language?
Returns true if at least one of the receiver's #languages is set to a value that was designated as acceptable by the originating request, if there was no originating request, or if no #languages have been set for a non-empty entity body.
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 227 def acceptable_language? req = self.request or return true # Lack of an accept-language field means all languages are accepted return true if req.accepted_languages.empty? # If no language is given for an existing entity body, there's no way # to know whether or not there's a better alternative return true if self.languages.empty? # If any of the languages present for the body are accepted, the # request is acceptable. Or at least that's what I got out of # reading RFC2616, Section 14.4. answer = self.languages.any? {|lang| req.accepts_language?(lang) } self.log.warn "Content-language %p NOT acceptable: %s" % [ self.languages, req.accepted_languages ] unless answer return answer end |
#better_charsets ⇒ Object
Returns Strelka::HTTPRequest::Charset objects for accepted character sets that have a higher qvalue than the one used by the current response.
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 471 def better_charsets req = self.request or return [] return [] unless self.content_type && self.content_type.start_with?( 'text/', 'application/' ) return [] unless req.headers.accept_charset current_qvalue = 0.0 charsets = req.accepted_charsets.sort current_charset = self.find_header_charset # If the current charset exists in the Accept-Charset: header, reset the current qvalue # to whatever its qvalue is if current_charset != Encoding::ASCII_8BIT charset = charsets.find {|mt| mt =~ current_charset } current_qvalue = charset.qvalue if charset end self.log.debug "Looking for better charsets than %p (%0.2f)" % [ current_charset, current_qvalue ] return charsets.sort.find_all do |cs| cs.qvalue > current_qvalue end end |
#better_encoding ⇒ Object
Returns Strelka::HTTPRequest::Encoding objects for accepted encodings that have a higher qvalue than the one used by the current response.
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 588 def better_encoding req = self.request or return [] return [] unless req.headers.accept_encoding current_qvalue = 0.0 encodings = req.accepted_encodings.sort current_encodings = self.encodings.dup current_encodings.unshift( 'identity' ) # Find the highest qvalue of the encodings that have been applied already current_qvalue = current_encodings.inject( current_qvalue ) do |qval, current_enc| qenc = encodings.find {|enc| enc =~ current_enc } or next qval qenc.qvalue > qval ? qenc.qvalue : qval end self.log.debug "Looking for better encodings than %p (%0.2f)" % [ current_encodings, current_qvalue ] return encodings.find_all do |enc| self.log.debug " %s (%0.2f) > %0.2f?" % [ enc, enc.qvalue, current_qvalue ] enc.qvalue > current_qvalue end end |
#better_languages ⇒ Object
Returns Strelka::HTTPRequest::Language objects for natural languages that have a higher qvalue than the current response's entity body (if any).
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 408 def better_languages req = self.request or return [] current_qvalue = 0.0 accepted_languages = req.accepted_languages.sort # If any of the current languages exists in the Accept-Language: header, reset # the current qvalue to the highest one among them unless self.languages.empty? current_qvalue = self.languages.reduce( current_qvalue ) do |qval, lang| accepted_lang = accepted_languages.find {|alang| alang =~ lang } or next qval qval > accepted_lang.qvalue ? qval : accepted_lang.qvalue end end self.log.debug "Looking for better languages than %p (%0.2f)" % [ self.languages.join(', '), current_qvalue ] return accepted_languages.find_all do |lang| lang.qvalue > current_qvalue end end |
#better_mediatypes ⇒ Object
Returns Strelka::HTTPRequest::MediaType objects for mediatypes that have a higher qvalue than the current response's entity body (if any).
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 299 def better_mediatypes req = self.request or return [] return [] unless req.headers.accept current_qvalue = 0.0 mediatypes = req.accepted_mediatypes.sort # If the current mediatype exists in the Accept: header, reset the current qvalue # to whatever its qvalue is if self.content_type mediatype = mediatypes.find {|mt| mt =~ self.content_type } current_qvalue = mediatype.qvalue if mediatype end self.log.debug "Looking for better mediatypes than %p (%0.2f)" % [ self.content_type, current_qvalue ] return mediatypes.find_all do |mt| mt.qvalue > current_qvalue end end |
#for(*mediatypes, &callback) ⇒ Object
Register a callback that will be called during transparent content
negotiation for the entity body if one or more of the specified
mediatypes is among the requested alternatives. The mediatypes
can be either mimetype Strings or Symbols that correspond to keys
in the BUILTIN_MIMETYPES hash. The callback will be called with
the desired mimetype, and should return the new value for the entity
body if it successfully transformed the body, or a false value if
the next alternative should be tried instead.
If successful, the response's body will be set to the new value,
its content_type set to the new mimetype, and its status changed
to HTTP::OK.
282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 282 def for( *mediatypes, &callback ) mediatypes.each do |mimetype| if mimetype.is_a?( Symbol ) mimetype = Strelka::HTTPResponse::Negotiation.mimetype_map[ mimetype ] or raise "No known mimetype mapped to %p" % [ mimetype ] end self.mediatype_callbacks[ mimetype ] = callback end # Include the 'Accept:' header in the 'Vary:' header self.vary_fields.add( 'accept' ) end |
#for_encoding(*codings, &callback) ⇒ Object
Register a callback that will be called during transparent content
negotiation for the entity body if one or more of the specified
codings is among the requested alternatives. The codings
are Strings in the form described by RFC2616, section 3.5. The
callback will be called with the coding name, and should
return the new value for the entity body if it has transformed the
bod. If successful, the response's body will be set to the new
value, and the coding name added to the appropriate headers.
576 577 578 579 580 581 582 583 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 576 def for_encoding( *codings, &callback ) codings.each do |coding| self.encoding_callbacks[ coding ] = callback end # Include the 'Accept-Encoding:' header in the 'Vary:' header self.vary_fields.add( 'accept-encoding' ) end |
#for_language(*language_tags, &callback) ⇒ Object
Register a callback that will be called during transparent content
negotiation for the entity body if one or more of the specified
language_tags is among the requested alternatives. The language_tags
are Strings in the form described by RFC2616, section 3.10. The
callback will be called with the desired language code, and should
return the new value for the entity body if it has value for the
body, or a false value if the next alternative should be tried
instead. If successful, the response's body will be set to the new
value, and its status changed to HTTP::OK.
396 397 398 399 400 401 402 403 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 396 def for_language( *, &callback ) .flatten.each do |lang| self.language_callbacks[ lang.to_sym ] = callback end # Include the 'Accept-Language:' header in the 'Vary:' header self.vary_fields.add( 'accept-language' ) end |
#initialize ⇒ Object
Add some instance variables for negotiation.
80 81 82 83 84 85 86 87 88 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 80 def initialize( * ) @mediatype_callbacks = {} @language_callbacks = {} @encoding_callbacks = {} @vary_fields = Set.new super end |
#mimetype_map ⇒ Object
The Hash of symbolic mediatypes of the form:
{ <name (Symbol)> => <mimetype> }
70 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 70 singleton_attr_reader :mimetype_map |
#negotiate ⇒ Object
Check for any negotiation that should happen and apply the necessary transforms if they're available.
156 157 158 159 160 161 162 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 156 def negotiate return if !self.request self.transform_content_type self.transform_language self.transform_charset self.transform_encoding end |
#negotiated_body ⇒ Object
Transform the entity body if it doesn't meet the criteria
148 149 150 151 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 148 def negotiated_body self.negotiate return self.body end |
#normalized_headers ⇒ Object
Overridden to add a Vary: header to outgoing headers if the response has any #vary_fields.
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 128 def normalized_headers headers = super unless self.vary_fields.empty? self.log.debug "Adding Vary header for %p" % [ self.vary_fields ] headers.vary = self.vary_fields.to_a.join( ', ' ) end return headers end |
#reset ⇒ Object
Overridden to reset content-negotiation callbacks, too.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 112 def reset super @mediatype_callbacks.clear @language_callbacks.clear @encoding_callbacks.clear # Not clearing the Vary: header for now, as it's useful in a 406 to # determine what accept-* headers can be modified to get an acceptable # response # @vary_fields.clear end |
#stringifiers ⇒ Object
The Hash of stringification callbacks, keyed by mimetype.
75 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 75 singleton_attr_reader :stringifiers |
#to_s ⇒ Object
Stringify the response -- overridden to use the negotiated body.
141 142 143 144 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 141 def to_s self.negotiate super end |
#transcode_body(charset) ⇒ Object
Try to transcode the entity body stream to one of the specified charsets. Returns
the succesful Encoding object if transcoding succeeded, or nil if transcoding
failed.
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 524 def transcode_body( charset ) unless enc = charset.encoding_object self.log.warn " unsupported charset: %s" % [ charset ] return false end begin # StringIOs get their internal string transcoded directly if self.body.respond_to?( :string ) self.body.string.encode!( enc ) return true # For other IO objects, the situation is trickier -- we can't know that # encoding will succeed for more-restrictive charsets, so we only do # automatic transcoding if the 'wanted' one is a Unicode charset. # This probably isn't perfect, either. # :FIXME: Probably need a list of exceptions, i.e., charsets that don't # always transcode nicely into Unicode. elsif self.body.respond_to?( :fileno ) && UNICODE_CHARSETS.include?( enc ) self.log.info "Assuming %s data can be transcoded into %s" % [ self.body.internal_encoding, enc ] # Don't close the FD when this IO goes out of scope oldbody = self.body oldbody.autoclose = false # Re-open the same file descriptor, but transcoding to the wanted encoding self.body = IO.for_fd( oldbody.fileno, internal_encoding: enc ) return true end rescue Encoding::UndefinedConversionError => err self.log.error "%p while transcoding: %s" % [ err.class, err. ] end return false end |
#transform_charset ⇒ Object
Iterate over the originating request's acceptable charsets in qvalue+listed order, attempting to transcode the current entity body if it
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 500 def transform_charset self.log.debug "Looking for charset transformations." if self.body.respond_to?( :string ) || self.body.respond_to?( :fileno ) # Try each charset that's better than what we have already self.better_charsets.each do |charset| self.log.debug " trying to transcode to: %s" % [ charset ] # If it succeeds, indicate that transcoding took place in the Vary header if self.transcode_body( charset ) self.log.debug " success; body is now %p" % [ charset ] self.vary_fields.add( 'accept-charset' ) break end end else self.log.warn "Don't know how to transcode a %p" % [ self.body.class ] end end |
#transform_content_type ⇒ Object
Iterate over the originating request's acceptable content types in qvalue+listed order, looking for a content negotiation callback for each mediatype. If any are found, they are tried in declared order until one returns a true-ish value, which becomes the new entity body. If the body object is not a String,
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 327 def transform_content_type self.log.debug "Applying content-type transforms (if any)" return if self.mediatype_callbacks.empty? self.log.debug " transform callbacks registered: %p" % [ self.mediatype_callbacks ] self.better_mediatypes.each do |mediatype| callbacks = self.mediatype_callbacks.find_all do |mimetype, _| mediatype =~ mimetype end if callbacks.empty? self.log.debug " no transforms for %s" % [ mediatype ] else self.log.debug " %d transform/s for %s" % [ callbacks.length, mediatype ] callbacks.each do |mimetype, callback| return if self.try_content_type_callback( mimetype, callback ) end end end end |
#transform_encoding ⇒ Object
Iterate over the originating request's acceptable encodings and apply each one in the order they were requested if they're available.
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 615 def transform_encoding return if self.encoding_callbacks.empty? self.log.debug "Looking for acceptable content codings" self.better_encoding.each do |enc| self.log.debug " looking for a callback for %p" % [ enc ] if (( callback = self.encoding_callbacks[enc.content_coding.to_sym] )) self.log.debug " trying callback %p for %p" % [ callback, enc ] if (( new_body = callback.call(enc.content_coding) )) self.log.debug " callback succeeded" self.body = new_body self.encodings << enc.content_coding break end elsif enc.content_coding == 'identity' && enc.qvalue.nonzero? self.log.debug " identity coding, no callback" break end end end |
#transform_language ⇒ Object
If there are any languages that have a higher qvalue than the one/s in #languages, look for a negotiation callback that provides that language. If any are found, they are tried in declared order until one returns a true-ish value, which becomes the new entity body.
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 437 def transform_language return if self.language_callbacks.empty? self.log.debug "Looking for language transformations" self.better_languages.uniq.each do |lang| callback = langcode = nil if lang.primary_tag langcode = lang.language_range callback = self.language_callbacks[ lang.primary_tag.to_sym ] else langcode, callback = self.language_callbacks.first end next unless callback self.log.debug " found a callback for %s: %p" % [ langcode, callback ] if (( new_body = callback.call(langcode) )) self.body = new_body self.languages.replace([ langcode.to_s ]) self.log.debug " success." break end end end |
#try_content_type_callback(mimetype, callback) ⇒ Object
Attempt to apply the callback for the specified mediatype to the entity
body, making the necessary changes to the request and returning true if
the callback returns a new entity body, or returning a false value if it doesn't.
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/strelka/httpresponse/negotiation.rb', line 352 def try_content_type_callback( mimetype, callback ) self.log.debug " trying content-type callback %p (%s)" % [ callback, mimetype ] new_body = begin callback.call( mimetype ) rescue => err self.log.error " %p raised from the callback for %s: %s" % [ err.class, mimetype, err. ] return false end self.log.debug " successfully transformed: %p! Setting up response." % [ new_body.class ] unless new_body.is_a?( String ) stringifiers = Strelka::HTTPResponse::Negotiation.stringifiers if stringifiers.key?( mimetype ) new_body = stringifiers[ mimetype ].call( new_body ) else self.log.debug " no stringifier registered for %p" % [ mimetype ] end else self.log.debug " body is already a String" end self.body = new_body self.content_type = mimetype.dup # :TODO: Why is this frozen? self.status ||= HTTP::OK return true end |