How to save case with http.get?

I have a requirement to send an HTTP header for a specific case of characters. I know this contradicts the RFC, but I have a requirement.

http.getseems to change the case when I propose a heading dictionary. How to keep case of characters?

+3
source share
5 answers

Based on Tin Man's answer that the library Net::HTTPinvokes the #downcaseheader (and all header files) in your custom key, here are a few additional options that don't render everything harmless Net::HTTP.

You can try the following:

custom_header_key = "X-miXEd-cASe"
def custom_header_key.downcase
  self
end

To avoid clearing the method cache, save the result above in the class level constant:

custom_header_key = "X-miXEd-cASe"
def custom_header_key.downcase
  self
end
CUSTOM_HEADER_KEY = custom_header_key

String :

class StringWithIdentityDowncase < String
  def downcase
    self
  end
end

custom_header_key = StringWithIdentityDowncase.new("X-miXEd-cASe")
+13

. , , - , , split capitalize, , 2004 .

:

require 'net/http'

class Net::HTTP::ImmutableHeaderKey
  attr_reader :key

  def initialize(key)
    @key = key
  end

  def downcase
    self
  end

  def capitalize
    self
  end

  def split(*)
    [self]
  end

  def hash
    key.hash
  end

  def eql?(other)
    key.eql? other.key.eql?
  end

  def to_s
    key
  end
end

.

request           = Net::HTTP::Get.new('/')
user_key          = Net::HTTP::ImmutableHeaderKey.new("user")
request[user_key] = "James"

require 'stringio'
StringIO.new.tap do |output|
  request.exec output, 'ver', 'path'
  puts output.string
end

# >> GET path HTTP/ver
# >> Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
# >> Accept: */*
# >> User-Agent: Ruby
# >> user: James
# >> 
+5

Mine - , , @yfeldblum , downcase , .


Net:: HTTP:: HTTPHeader downcase.

, , . , HTTPHeader downcase .

module HTTPHeader

  def initialize_http_header(initheader)
    @header = {}
    return unless initheader
    initheader.each do |key, value|
      warn "net/http: warning: duplicated HTTP header: #{key}" if key?(key) and $VERBOSE
      @header[key] = [value.strip]
    end
  end

  def [](key)
    a = @header[key] or return nil
    a.join(', ')
  end

  def []=(key, val)
    unless val
      @header.delete key
      return val
    end
    @header[key] = [val]
  end

  def add_field(key, val)
    if @header.key?(key)
      @header[key].push val
    else
      @header[key] = [val]
    end
  end

  def get_fields(key)
    return nil unless @header[key]
    @header[key].dup
  end

  def fetch(key, *args, &block)   #:yield: +key+
    a = @header.fetch(key, *args, &block)
    a.kind_of?(Array) ? a.join(', ') : a
  end

  # Removes a header field.
  def delete(key)
    @header.delete(key)
  end

  # true if +key+ header exists.
  def key?(key)
    @header.key?(key)
  end

  def tokens(vals)
    return [] unless vals
    vals.map {|v| v.split(',') }.flatten\
    .reject {|str| str.strip.empty? }\
    .map {|tok| tok.strip }
  end

end

, , .

Ruby Net:: HTTP, , , , Curl libcurl.

+2

Joshua Cheek , Ruby 2.3

:

class Net::HTTP::ImmutableHeaderKey
  ...

  def to_s
    caller.first.match(/capitalize/) ? self : @key
  end
end
+1

net/generic_request # write_header.

# 'net/generic_request' line 319
def write_header(sock, ver, path)
  customheaders = {
    "My-Custom-Header" => "MY-CUSTOM-HEADER",
    "Another-Custom-Header" => "aNoThErCuStOmHeAdEr"
  }
  buf = "#{@method} #{path} HTTP/#{ver}\r\n"
  each_capitalized do |k,v|
    customheaders.key?(k) ? kk = customheaders[k] : kk = k
    buf << "#{kk}: #{v}\r\n"
  end
  buf << "\r\n"
  sock.write buf
end

and you don’t need to rewrite the whole net / http / header, net / generic_request and net / http chain. This is not the best solution, but it is the easiest one I guess, and at least the number of monkey fixes.

Hope this helps.

0
source

Source: https://habr.com/ru/post/1742726/


All Articles