lib/roda/response.rb in roda-3.69.0 vs lib/roda/response.rb in roda-3.70.0
- old
+ new
@@ -4,10 +4,29 @@
require 'rack/headers'
rescue LoadError
end
class Roda
+ # Contains constants for response headers. This approach is used so that all
+ # headers used internally by Roda can be lower case on Rack 3, so that it is
+ # possible to use a plain hash of response headers instead of using Rack::Headers.
+ module RodaResponseHeaders
+ headers = %w'Allow Cache-Control Content-Disposition Content-Encoding Content-Length
+ Content-Security-Policy Content-Security-Policy-Report-Only Content-Type
+ ETag Expires Last-Modified Link Location Set-Cookie Transfer-Encoding Vary'.freeze.each(&:freeze)
+
+ if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
+ headers.each do |mixed_case|
+ const_set(mixed_case.gsub('-', '_').upcase!.to_sym, mixed_case.downcase.freeze)
+ end
+ else
+ headers.each do |mixed_case|
+ const_set(mixed_case.gsub('-', '_').upcase!.to_sym, mixed_case.freeze)
+ end
+ end
+ end
+
# Base class used for Roda responses. The instance methods for this
# class are added by Roda::RodaPlugins::Base::ResponseMethods, the class
# methods are added by Roda::RodaPlugins::Base::ResponseClassMethods.
class RodaResponse
@roda_class = ::Roda
@@ -28,11 +47,11 @@
end
end
# Instance methods for RodaResponse
module ResponseMethods
- DEFAULT_HEADERS = {"Content-Type" => "text/html".freeze}.freeze
+ DEFAULT_HEADERS = {RodaResponseHeaders::CONTENT_TYPE => "text/html".freeze}.freeze
# The body for the current response.
attr_reader :body
# The hash of response headers for the current response.
@@ -40,24 +59,15 @@
# The status code to use for the response. If none is given, will use 200
# code for non-empty responses and a 404 code for empty responses.
attr_accessor :status
- if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
- # Set the default headers when creating a response.
- def initialize
- @headers = Rack::Headers.new
- @body = []
- @length = 0
- end
- else
- # Set the default headers when creating a response.
- def initialize
- @headers = {}
- @body = []
- @length = 0
- end
+ # Set the default headers when creating a response.
+ def initialize
+ @headers = _initialize_headers
+ @body = []
+ @length = 0
end
# Return the response header with the given key. Example:
#
# response['Content-Type'] # => 'text/html'
@@ -106,19 +116,19 @@
h = @headers
if b.empty?
s = @status || 404
if (s == 304 || s == 204 || (s >= 100 && s <= 199))
- h.delete("Content-Type")
+ h.delete(RodaResponseHeaders::CONTENT_TYPE)
elsif s == 205
empty_205_headers(h)
else
- h["Content-Length"] ||= '0'
+ h[RodaResponseHeaders::CONTENT_LENGTH] ||= '0'
end
else
s = @status || default_status
- h["Content-Length"] ||= @length.to_s
+ h[RodaResponseHeaders::CONTENT_LENGTH] ||= @length.to_s
end
[s, h, b]
end
@@ -147,11 +157,11 @@
# to the given status. Example:
#
# response.redirect('foo', 301)
# response.redirect('bar')
def redirect(path, status = 302)
- @headers["Location"] = path
+ @headers[RodaResponseHeaders::LOCATION] = path
@status = status
nil
end
# Return the Roda class related to this response.
@@ -169,21 +179,33 @@
nil
end
private
+ if defined?(Rack::Headers) && Rack::Headers.is_a?(Class)
+ # Use Rack::Headers for headers by default on Rack 3
+ def _initialize_headers
+ Rack::Headers.new
+ end
+ else
+ # Use plain hash for headers by default on Rack 1-2
+ def _initialize_headers
+ {}
+ end
+ end
+
if Rack.release < '2.0.2'
# Don't use a content length for empty 205 responses on
# rack 1, as it violates Rack::Lint in that version.
def empty_205_headers(headers)
- headers.delete("Content-Type")
- headers.delete("Content-Length")
+ headers.delete(RodaResponseHeaders::CONTENT_TYPE)
+ headers.delete(RodaResponseHeaders::CONTENT_LENGTH)
end
else
# Set the content length for empty 205 responses to 0
def empty_205_headers(headers)
- headers.delete("Content-Type")
- headers["Content-Length"] = '0'
+ headers.delete(RodaResponseHeaders::CONTENT_TYPE)
+ headers[RodaResponseHeaders::CONTENT_LENGTH] = '0'
end
end
# For each default header, if a header has not already been set for the
# response, set the header in the response.