Skip to content

Commit

Permalink
Optimizes normalize_headers for performance
Browse files Browse the repository at this point in the history
Optimizes the `WebMock::Util::Headers.normalize_headers` method to:

* Create less objects
* Avoid using Regexp where possible
* Hoists constants

More details can be found in the related issue, including performance
benchmarks:

#1027
  • Loading branch information
Brandon Weaver committed Jun 6, 2023
1 parent 833291d commit 1249b51
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions lib/webmock/util/headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ module Util

class Headers

STANDARD_HEADER_DELIMITER = '-'.freeze
NONSTANDARD_HEADER_DELIMITER = '_'.freeze
JOIN = ', '.freeze

def self.normalize_headers(headers)
return nil unless headers
array = headers.map { |name, value|
[name.to_s.split(/_|-/).map { |segment| segment.capitalize }.join("-"),
case value

headers.each_with_object({}) do |(name, value), new_headers|
new_headers[normalize_name(name)] =
case value
when Regexp then value
when Array then (value.size == 1) ? value.first.to_s : value.map {|v| v.to_s}.sort
when Array then (value.size == 1) ? value.first.to_s : value.map(&:to_s).sort
else value.to_s
end
]
}
Hash[*array.inject([]) {|r,x| r + x}]
end
end
end

def self.sorted_headers_string(headers)
Expand Down Expand Up @@ -57,6 +60,15 @@ def self.basic_auth_header(*credentials)
"Basic #{Base64.strict_encode64(credentials.join(':')).chomp}"
end

def self.normalize_name(name)
name
.to_s
.tr(NONSTANDARD_HEADER_DELIMITER, STANDARD_HEADER_DELIMITER)
.split(STANDARD_HEADER_DELIMITER)
.map!(&:capitalize)
.join(STANDARD_HEADER_DELIMITER)
end

end

end
Expand Down

0 comments on commit 1249b51

Please sign in to comment.