-
Notifications
You must be signed in to change notification settings - Fork 322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Preserve header casing as specified #576
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,10 @@ class Headers | |
|
||
# Class constructor. | ||
def initialize | ||
# The @pile stores each header value using a three element array: | ||
# 0 - the normalized header key, used for lookup | ||
# 1 - the header key as it will be sent with a request | ||
# 2 - the value | ||
@pile = [] | ||
end | ||
|
||
|
@@ -45,20 +49,39 @@ def delete(name) | |
|
||
# Appends header. | ||
# | ||
# @param [#to_s] name header name | ||
# @param [String, Symbol] name header name. When specified as a string, the | ||
# name is sent as-is. When specified as a symbol, the name is converted | ||
# to a string of capitalized words separated by a dash. Word boundaries | ||
# are determined by an underscore (`_`) or a dash (`-`). | ||
# Ex: `:content_type` is sent as `"Content-Type"`, and `"auth_key"` (string) | ||
# is sent as `"auth_key"`. | ||
# @param [Array<#to_s>, #to_s] value header value(s) to be appended | ||
# @return [void] | ||
def add(name, value) | ||
name = normalize_header name.to_s | ||
Array(value).each { |v| @pile << [name, validate_value(v)] } | ||
lookup_name = normalize_header(name.to_s) | ||
wire_name = case name | ||
when String | ||
name | ||
when Symbol | ||
lookup_name | ||
else | ||
raise HTTP::HeaderError, "HTTP header must be a String or Symbol: #{name.inspect}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should raise only if key is no ot responding to to_s and not a Symbol. Something like: if name.is_a? Symbol
# ...
elsif name.respond_to? :to_s
# ...
else
raise
end There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see how that is helpful. Almost everything in ruby responds to If you want to allow more than just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I agree. Then we need to update api doc to reflect this change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want to want to keep my current strict implementation (only allow String or Symbol), or do you want to use the more relaxed "anything that supports an implicit conversion to string (ie. responds to I think being strict makes sense here, especially since we have different behavior based on the data type. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with your way. Strict Symbol or String. |
||
end | ||
Array(value).each do |v| | ||
@pile << [ | ||
lookup_name, | ||
wire_name, | ||
validate_value(v) | ||
] | ||
end | ||
end | ||
|
||
# Returns list of header values if any. | ||
# | ||
# @return [Array<String>] | ||
def get(name) | ||
name = normalize_header name.to_s | ||
@pile.select { |k, _| k == name }.map { |_, v| v } | ||
@pile.select { |k, _| k == name }.map { |_, _, v| v } | ||
end | ||
|
||
# Smart version of {#get}. | ||
|
@@ -96,7 +119,7 @@ def to_h | |
# | ||
# @return [Array<[String, String]>] | ||
def to_a | ||
@pile.map { |pair| pair.map(&:dup) } | ||
@pile.map { |item| item[1..2] } | ||
end | ||
|
||
# Returns human-readable representation of `self` instance. | ||
|
@@ -110,7 +133,7 @@ def inspect | |
# | ||
# @return [Array<String>] | ||
def keys | ||
@pile.map { |k, _| k }.uniq | ||
@pile.map { |_, k, _| k }.uniq | ||
end | ||
|
||
# Compares headers to another Headers or Array of key/value pairs | ||
|
@@ -119,7 +142,7 @@ def keys | |
def ==(other) | ||
return false unless other.respond_to? :to_a | ||
|
||
@pile == other.to_a | ||
to_a == other.to_a | ||
end | ||
|
||
# Calls the given block once for each key/value pair in headers container. | ||
|
@@ -129,7 +152,7 @@ def ==(other) | |
def each | ||
return to_enum(__method__) unless block_given? | ||
|
||
@pile.each { |arr| yield(arr) } | ||
@pile.each { |item| yield(item[1..2]) } | ||
self | ||
end | ||
|
||
|
@@ -152,7 +175,7 @@ def each | |
# @api private | ||
def initialize_copy(orig) | ||
super | ||
@pile = to_a | ||
@pile = @pile.map(&:dup) | ||
end | ||
|
||
# Merges `other` headers into `self`. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to introduce optional keyword:
Naturally, when normalize is false, no normalization should be done for the wire. When true - force normalization, and when nil - type dependent normalization.