diff --git a/.github/workflows/test-external.yaml b/.github/workflows/test-external.yaml index d55882cea..bcf7a6c72 100644 --- a/.github/workflows/test-external.yaml +++ b/.github/workflows/test-external.yaml @@ -11,7 +11,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - ruby: ['2.7', '3.0', '3.1'] + ruby: ['3.0', '3.1', '3.2', '3.3'] runs-on: ${{matrix.os}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a7aa440..c1f38daf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/). +## Unreleased + +## [3.0.9] - 2024-01-31 + +- Fix incorrect content-length header that was emitted when `Rack::Response#write` was used in some situations. ([#2150](https://github.com/rack/rack/pull/2150), [@mattbrictson]) + +## [3.0.8] - 2023-06-14 + +- Fix some unused variable verbose warnings. ([#2084](https://github.com/rack/rack/pull/2084), [@jeremyevans], [@skipkayhil](https://github.com/skipkayhil)) + ## [3.0.7] - 2023-03-16 - Make query parameters without `=` have `nil` values. ([#2059](https://github.com/rack/rack/pull/2059), [@jeremyevans]) diff --git a/lib/rack/media_type.rb b/lib/rack/media_type.rb index ff3145deb..7fc1e39db 100644 --- a/lib/rack/media_type.rb +++ b/lib/rack/media_type.rb @@ -4,7 +4,7 @@ module Rack # Rack::MediaType parse media type and parameters out of content_type string class MediaType - SPLIT_PATTERN = %r{\s*[;,]\s*} + SPLIT_PATTERN = /[;,]/ class << self # The media type (type/subtype) portion of the CONTENT_TYPE header @@ -15,7 +15,11 @@ class << self # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 def type(content_type) return nil unless content_type - content_type.split(SPLIT_PATTERN, 2).first.tap(&:downcase!) + if type = content_type.split(SPLIT_PATTERN, 2).first + type.rstrip! + type.downcase! + type + end end # The media type parameters provided in CONTENT_TYPE as a Hash, or @@ -27,9 +31,10 @@ def params(content_type) return {} if content_type.nil? content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh| + s.strip! k, v = s.split('=', 2) - - hsh[k.tap(&:downcase!)] = strip_doublequotes(v) + k.downcase! + hsh[k] = strip_doublequotes(v) end end diff --git a/lib/rack/response.rb b/lib/rack/response.rb index f24683bcb..b9b02c272 100644 --- a/lib/rack/response.rb +++ b/lib/rack/response.rb @@ -328,6 +328,8 @@ def buffered_body! @body.each do |part| @length += part.to_s.bytesize end + + @buffered = true elsif @body.respond_to?(:each) # Turn the user supplied body into a buffered array: body = @body diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb index 99d696dbf..f91838b37 100644 --- a/lib/rack/utils.rb +++ b/lib/rack/utils.rb @@ -143,8 +143,8 @@ def build_nested_query(value, prefix = nil) end def q_values(q_value_header) - q_value_header.to_s.split(/\s*,\s*/).map do |part| - value, parameters = part.split(/\s*;\s*/, 2) + q_value_header.to_s.split(',').map do |part| + value, parameters = part.split(';', 2).map(&:strip) quality = 1.0 if parameters && (md = /\Aq=([\d.]+)/.match(parameters)) quality = md[1].to_f @@ -157,9 +157,10 @@ def forwarded_values(forwarded_header) return nil unless forwarded_header forwarded_header = forwarded_header.to_s.gsub("\n", ";") - forwarded_header.split(/\s*;\s*/).each_with_object({}) do |field, values| - field.split(/\s*,\s*/).each do |pair| - return nil unless pair =~ /\A\s*(by|for|host|proto)\s*=\s*"?([^"]+)"?\s*\Z/i + forwarded_header.split(';').each_with_object({}) do |field, values| + field.split(',').each do |pair| + pair = pair.split('=').map(&:strip).join('=') + return nil unless pair =~ /\A(by|for|host|proto)="?([^"]+)"?\Z/i (values[$1.downcase.to_sym] ||= []) << $2 end end @@ -458,6 +459,9 @@ def get_byte_ranges(http_range, size) end ranges << (r0..r1) if r0 <= r1 end + + return [] if ranges.map(&:size).sum > size + ranges end diff --git a/lib/rack/version.rb b/lib/rack/version.rb index e634f23ae..8817699e1 100644 --- a/lib/rack/version.rb +++ b/lib/rack/version.rb @@ -25,7 +25,7 @@ def self.version VERSION end - RELEASE = "3.0.8" + RELEASE = "3.0.9.1" # Return the Rack release as a dotted string. def self.release diff --git a/test/spec_response.rb b/test/spec_response.rb index ef8aa481c..11e64d61f 100644 --- a/test/spec_response.rb +++ b/test/spec_response.rb @@ -412,7 +412,7 @@ def object_with_each.each status.must_equal 404 end - it "correctly updates content-type when writing when not initialized with body" do + it "correctly updates content-length when writing when initialized without body" do r = Rack::Response.new r.write('foo') r.write('bar') @@ -423,20 +423,39 @@ def object_with_each.each header['content-length'].must_equal '9' end - it "correctly updates content-type when writing when initialized with body" do + it "correctly updates content-length when writing when initialized with Array body" do + r = Rack::Response.new(["foo"]) + r.write('bar') + r.write('baz') + _, header, body = r.finish + str = "".dup; body.each { |part| str << part } + str.must_equal "foobarbaz" + header['content-length'].must_equal '9' + end + + it "correctly updates content-length when writing when initialized with String body" do + r = Rack::Response.new("foo") + r.write('bar') + r.write('baz') + _, header, body = r.finish + str = "".dup; body.each { |part| str << part } + str.must_equal "foobarbaz" + header['content-length'].must_equal '9' + end + + it "correctly updates content-length when writing when initialized with object body that responds to #each" do obj = Object.new def obj.each yield 'foo' yield 'bar' end - ["foobar", ["foo", "bar"], obj].each do - r = Rack::Response.new(["foo", "bar"]) - r.write('baz') - _, header, body = r.finish - str = "".dup; body.each { |part| str << part } - str.must_equal "foobarbaz" - header['content-length'].must_equal '9' - end + r = Rack::Response.new(obj) + r.write('baz') + r.write('baz') + _, header, body = r.finish + str = "".dup; body.each { |part| str << part } + str.must_equal "foobarbazbaz" + header['content-length'].must_equal '12' end it "doesn't return invalid responses" do diff --git a/test/spec_utils.rb b/test/spec_utils.rb index c4f9b27fa..2165c5a6a 100644 --- a/test/spec_utils.rb +++ b/test/spec_utils.rb @@ -716,6 +716,10 @@ def initialize(*) end describe Rack::Utils, "get_byte_ranges" do + it "returns an empty list if the sum of the ranges is too large" do + assert_equal [], Rack::Utils.byte_ranges({ "HTTP_RANGE" => "bytes=0-20,0-500" }, 500) + end + deprecated "pase simple byte ranges from env" do Rack::Utils.byte_ranges({ "HTTP_RANGE" => "bytes=123-456" }, 500).must_equal [(123..456)] end pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy