module Net::HTTPHeader
Модуль HTTPHeader определяет методы для чтения и записи заголовков HTTP.
Он используется как mixin другими классами для обеспечения доступа к значениям заголовков HTTP по принципу хеш-таблицы. В отличие от прямого доступа к хешу, HTTPHeader обеспечивает доступ через ключи без учёта регистра. Он также предоставляет методы для доступа к часто используемым значениям заголовков HTTP в более удобных форматах.
Публичные методы экземпляра
# File lib/net/http/header.rb, line 37
def [](key)
a = @header[key.downcase] or return nil
a.join(', ')
end Возвращает поле заголовка, соответствующее ключу без учёта регистра. Например, ключ «Content-Type» может вернуть «text/html»
# File lib/net/http/header.rb, line 43
def []=(key, val)
unless val
@header.delete key.downcase
return val
end
set_field(key, val)
end Устанавливает поле заголовка, соответствующее ключу без учёта регистра.
# File lib/net/http/header.rb, line 66
def add_field(key, val)
if @header.key?(key.downcase)
append_field_value(@header[key.downcase], val)
else
set_field(key, val)
end
end - Ruby 1.8.3
-
Добавляет значение к именованному полю заголовка, вместо замены его значения. Второй аргумент
valдолжен быть строкой. См. также []=, [] и get_fields.request.add_field 'X-My-Header', 'a' p request['X-My-Header'] #=> "a" p request.get_fields('X-My-Header') #=> ["a"] request.add_field 'X-My-Header', 'b' p request['X-My-Header'] #=> "a, b" p request.get_fields('X-My-Header') #=> ["a", "b"] request.add_field 'X-My-Header', 'c' p request['X-My-Header'] #=> "a, b, c" p request.get_fields('X-My-Header') #=> ["a", "b", "c"]
# File lib/net/http/header.rb, line 465 def basic_auth(account, password) @header['authorization'] = [basic_encode(account, password)] end
Set заголовок Authorization: для авторизации «Basic».
# File lib/net/http/header.rb, line 326 def chunked? return false unless @header['transfer-encoding'] field = self['Transfer-Encoding'] (/(?:\A|[^\-\w])chunked(?![\-\w])/i =~ field) ? true : false end
Возвращает «true», если заголовок «transfer-encoding» присутствует и установлен в «chunked». Это функция HTTP/1.1, позволяющая отправлять контент «частями» без предварительного указания всей длины контента.
# File lib/net/http/header.rb, line 479
def connection_close?
token = /(?:\A|,)\s*close\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
@header['proxy-connection']&.grep(token) {return true}
false
end # File lib/net/http/header.rb, line 486
def connection_keep_alive?
token = /(?:\A|,)\s*keep-alive\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
@header['proxy-connection']&.grep(token) {return true}
false
end # File lib/net/http/header.rb, line 307
def content_length
return nil unless key?('Content-Length')
len = self['Content-Length'].slice(/\d+/) or
raise Net::HTTPHeaderSyntaxError, 'wrong Content-Length format'
len.to_i
end Возвращает объект Integer, представляющий поле заголовка HTTP Content-Length:, или nil если это поле не было предоставлено.
# File lib/net/http/header.rb, line 314
def content_length=(len)
unless len
@header.delete 'content-length'
return nil
end
@header['content-length'] = [len.to_i.to_s]
end # File lib/net/http/header.rb, line 336
def content_range
return nil unless @header['content-range']
m = %r<bytes\s+(\d+)-(\d+)/(\d+|\*)>i.match(self['Content-Range']) or
raise Net::HTTPHeaderSyntaxError, 'wrong Content-Range format'
m[1].to_i .. m[2].to_i
end Возвращает объект Range, представляющий значение поля заголовка Content-Range:. Для частичного тела сущности это указывает, где этот фрагмент находится в полном теле сущности, как диапазон смещений байтов.
# File lib/net/http/header.rb, line 351
def content_type
return nil unless main_type()
if sub_type()
then "#{main_type()}/#{sub_type()}"
else main_type()
end
end Возвращает строку типа контента, например «text/html». Этот метод возвращает nil, если поле заголовка Content-Type: не существует.
# File lib/net/http/header.rb, line 183 def delete(key) @header.delete(key.downcase) end
Удаляет поле заголовка, указанное по ключу без учёта регистра.
# File lib/net/http/header.rb, line 208
def each_capitalized
block_given? or return enum_for(__method__) { @header.size }
@header.each do |k,v|
yield capitalize(k), v.join(', ')
end
end Как и для each_header, за исключением того, что ключи предоставляются в заглавной форме.
Обратите внимание, что имена заголовков заглавны систематически; заглавные буквы могут не совпадать с теми, которые используются удалённым HTTP-сервером в его ответе.
Возвращает перечислитель, если блок не задан.
# File lib/net/http/header.rb, line 164
def each_capitalized_name #:yield: +key+
block_given? or return enum_for(__method__) { @header.size }
@header.each_key do |k|
yield capitalize(k)
end
end Итерирует по именам заголовков в заголовке, передавая имена заголовков в заглавной форме в блок кода.
Обратите внимание, что имена заголовков заглавны систематически; заглавные буквы могут не совпадать с теми, которые используются удалённым HTTP-сервером в его ответе.
Возвращает перечислитель, если блок не задан.
# File lib/net/http/header.rb, line 136
def each_header #:yield: +key+, +value+
block_given? or return enum_for(__method__) { @header.size }
@header.each do |k,va|
yield k, va.join(', ')
end
end Итерирует по именам и значениям заголовков, передавая имя и значение в предоставленный блок кода.
Возвращает перечислитель, если блок не задан.
Пример:
response.header.each_header {|key,value| puts "#{key} = #{value}" }
# File lib/net/http/header.rb, line 149
def each_name(&block) #:yield: +key+
block_given? or return enum_for(__method__) { @header.size }
@header.each_key(&block)
end Итерирует по именам заголовков в заголовке, передавая каждое имя заголовка в блок кода.
Возвращает перечислитель, если блок не задан.
# File lib/net/http/header.rb, line 175
def each_value #:yield: +value+
block_given? or return enum_for(__method__) { @header.size }
@header.each_value do |va|
yield va.join(', ')
end
end Итерирует по значениям заголовков, передавая каждое значение в блок кода.
Возвращает перечислитель, если блок не задан.
# File lib/net/http/header.rb, line 122
def fetch(key, *args, &block) #:yield: +key+
a = @header.fetch(key.downcase, *args, &block)
a.kind_of?(Array) ? a.join(', ') : a
end Возвращает поле заголовка, соответствующее ключу без учёта регистра. Возвращает значение по умолчанию args, или результат блока, или вызывает IndexError, если нет поля заголовка с именем key См. Hash#fetch
# File lib/net/http/header.rb, line 113 def get_fields(key) return nil unless @header[key.downcase] @header[key.downcase].dup end
- Ruby 1.8.3
-
Возвращает массив строк полей заголовка, соответствующих регистронезависимому
key. Этот метод позволяет получить дублированные поля заголовка без какой-либо обработки. См. также [].p response.get_fields('Set-Cookie') #=> ["session=al98axx; expires=Fri, 31-Dec-1999 23:58:23", "query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"] p response['Set-Cookie'] #=> "session=al98axx; expires=Fri, 31-Dec-1999 23:58:23, query=rubyscript; expires=Fri, 31-Dec-1999 23:58:23"
# File lib/net/http/header.rb, line 12
def initialize_http_header(initheader)
@header = {}
return unless initheader
initheader.each do |key, value|
warn "net/http: duplicated HTTP header: #{key}", uplevel: 1 if key?(key) and $VERBOSE
if value.nil?
warn "net/http: nil HTTP header: #{key}", uplevel: 1 if $VERBOSE
else
value = value.strip # raise error for invalid byte sequences
if value.count("\r\n") > 0
raise ArgumentError, 'header field value cannot include CR/LF'
end
@header[key.downcase] = [value]
end
end
end # File lib/net/http/header.rb, line 188 def key?(key) @header.key?(key.downcase) end
true, если существует заголовок key.
# File lib/net/http/header.rb, line 361
def main_type
return nil unless @header['content-type']
self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.strip
end Возвращает строку типа контента, например, «text». Этот метод возвращает nil, если поле заголовка Content-Type: не существует.
# File lib/net/http/header.rb, line 470 def proxy_basic_auth(account, password) @header['proxy-authorization'] = [basic_encode(account, password)] end
Set Заголовок Proxy-Authorization: для авторизации «Basic».
# File lib/net/http/header.rb, line 224
def range
return nil unless @header['range']
value = self['Range']
# byte-range-set = *( "," OWS ) ( byte-range-spec / suffix-byte-range-spec )
# *( OWS "," [ OWS ( byte-range-spec / suffix-byte-range-spec ) ] )
# corrected collected ABNF
# http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#section-5.4.1
# http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#appendix-C
# http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-19#section-3.2.5
unless /\Abytes=((?:,[ \t]*)*(?:\d+-\d*|-\d+)(?:[ \t]*,(?:[ \t]*\d+-\d*|-\d+)?)*)\z/ =~ value
raise Net::HTTPHeaderSyntaxError, "invalid syntax for byte-ranges-specifier: '#{value}'"
end
byte_range_set = $1
result = byte_range_set.split(/,/).map {|spec|
m = /(\d+)?\s*-\s*(\d+)?/i.match(spec) or
raise Net::HTTPHeaderSyntaxError, "invalid byte-range-spec: '#{spec}'"
d1 = m[1].to_i
d2 = m[2].to_i
if m[1] and m[2]
if d1 > d2
raise Net::HTTPHeaderSyntaxError, "last-byte-pos MUST greater than or equal to first-byte-pos but '#{spec}'"
end
d1..d2
elsif m[1]
d1..-1
elsif m[2]
-d2..-1
else
raise Net::HTTPHeaderSyntaxError, 'range is not specified'
end
}
# if result.empty?
# byte-range-set must include at least one byte-range-spec or suffix-byte-range-spec
# but above regexp already denies it.
if result.size == 1 && result[0].begin == 0 && result[0].end == -1
raise Net::HTTPHeaderSyntaxError, 'only one suffix-byte-range-spec with zero suffix-length'
end
result
end Возвращает массив объектов Range, которые представляют поле заголовка Range: HTTP, или nil, если такого заголовка нет.
# File lib/net/http/header.rb, line 344 def range_length r = content_range() or return nil r.end - r.begin + 1 end
Длина диапазона, представленного в заголовке Content-Range:.
# File lib/net/http/header.rb, line 394
def set_content_type(type, params = {})
@header['content-type'] = [type + params.map{|k,v|"; #{k}=#{v}"}.join('')]
end Устанавливает тип контента в заголовке HTTP. type должен быть полным типом контента HTTP, например, «text/html». params — это необязательный Hash параметров, которые нужно добавить после типа контента, например, {'charset' => 'iso-8859-1'}
# File lib/net/http/header.rb, line 450
def set_form(params, enctype='application/x-www-form-urlencoded', formopt={})
@body_data = params
@body = nil
@body_stream = nil
@form_option = formopt
case enctype
when /\Aapplication\/x-www-form-urlencoded\z/i,
/\Amultipart\/form-data\z/i
self.content_type = enctype
else
raise ArgumentError, "invalid enctype: #{enctype}"
end
end Set Набор данных HTML-формы. params — это набор данных формы; это массив массивов или Hash +enctype — это тип для кодирования набора данных формы. Это application/x-www-form-urlencoded или multipart/form-data. formopt — это необязательный хэш для указания детали.
- boundary
-
граница сообщения multipart
- charset
-
кодировка сообщения. Все имена и значения полей, не являющихся файлами, кодируются как кодировка.
Каждый элемент params — это массив и содержит следующие элементы:
-
name -
имя поля
-
value -
значение поля, оно должно быть строкой или File
-
opt -
необязательный хэш для указания дополнительной информации
Каждый элемент является полем файла или обычным полем. Если value является объектом File или opt имеет ключ filename, элемент обрабатывается как поле файла.
Если Transfer-Encoding установлен как chunked, это отправляет запрос в кодировке chunked. Поскольку кодировка chunked является функцией HTTP/1.1, вы должны подтвердить, что сервер поддерживает HTTP/1.1, прежде чем отправлять его.
Пример:
http.set_form([["q", "ruby"], ["lang", "en"]])
См. также RFC 2388, RFC 2616, HTML 4.01 и HTML5
# File lib/net/http/header.rb, line 413 def set_form_data(params, sep = '&') query = URI.encode_www_form(params) query.gsub!(/&/, sep) if sep != '&' self.body = query self.content_type = 'application/x-www-form-urlencoded' end
Set поля заголовка и тело из данных HTML-формы. params должен быть массивом массивов или Hash, содержащим данные HTML-формы. Необязательный аргумент sep означает разделитель записей данных.
Значения кодируются по URL-адресу по мере необходимости, а тип контента устанавливается в application/x-www-form-urlencoded
Пример:
http.form_data = {"q" => "ruby", "lang" => "en"}
http.form_data = {"q" => ["ruby", "perl"], "lang" => "en"}
http.set_form_data({"q" => "ruby", "lang" => "en"}, ';')
# File lib/net/http/header.rb, line 274
def set_range(r, e = nil)
unless r
@header.delete 'range'
return r
end
r = (r...r+e) if e
case r
when Numeric
n = r.to_i
rangestr = (n > 0 ? "0-#{n-1}" : "-#{-n}")
when Range
first = r.first
last = r.end
last -= 1 if r.exclude_end?
if last == -1
rangestr = (first > 0 ? "#{first}-" : "-#{-first}")
else
raise Net::HTTPHeaderSyntaxError, 'range.first is negative' if first < 0
raise Net::HTTPHeaderSyntaxError, 'range.last is negative' if last < 0
raise Net::HTTPHeaderSyntaxError, 'must be .first < .last' if first > last
rangestr = "#{first}-#{last}"
end
else
raise TypeError, 'Range/Integer is required'
end
@header['range'] = ["bytes=#{rangestr}"]
r
end Устанавливает заголовок HTTP Range:. Принимает либо объект Range в качестве единственного аргумента, либо начальный индекс и длину от этого индекса. Пример:
req.range = (0..1023) req.set_range 0, 1023
# File lib/net/http/header.rb, line 369
def sub_type
return nil unless @header['content-type']
_, sub = *self['Content-Type'].split(';').first.to_s.split('/')
return nil unless sub
sub.strip
end Возвращает строку типа контента, например, «html». Этот метод возвращает nil, если поле заголовка Content-Type: не существует или подтип не задан (например, «Content-Type: text»).
# File lib/net/http/header.rb, line 197 def to_hash @header.dup end
Возвращает Hash, состоящий из имен заголовков и массива значений. например, {“cache-control” => [“private”],
"content-type" => ["text/html"], "date" => ["Wed, 22 Jun 2005 22:11:50 GMT"]}
# File lib/net/http/header.rb, line 379
def type_params
result = {}
list = self['Content-Type'].to_s.split(';')
list.shift
list.each do |param|
k, v = *param.split('=', 2)
result[k.strip] = v.strip
end
result
end Любые параметры, указанные для типа контента, возвращаются как Hash. Например, заголовок Content-Type: text/html; charset=EUC-JP приведет к тому, что #type_params вернет {'charset' => 'EUC-JP'}
Приватные методы экземпляра
# File lib/net/http/header.rb, line 89
def append_field_value(ary, val)
case val
when Enumerable
val.each{|x| append_field_value(ary, x)}
else
val = val.to_s
if /[\r\n]/n.match?(val.b)
raise ArgumentError, 'header field value cannot include CR/LF'
end
ary.push val
end
end # File lib/net/http/header.rb, line 474
def basic_encode(account, password)
'Basic ' + ["#{account}:#{password}"].pack('m0')
end # File lib/net/http/header.rb, line 217
def capitalize(name)
name.to_s.split(/-/).map {|s| s.capitalize }.join('-')
end # File lib/net/http/header.rb, line 74
def set_field(key, val)
case val
when Enumerable
ary = []
append_field_value(ary, val)
@header[key.downcase] = ary
else
val = val.to_s # for compatibility use to_s instead of to_str
if val.b.count("\r\n") > 0
raise ArgumentError, 'header field value cannot include CR/LF'
end
@header[key.downcase] = [val]
end
end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.