1. Net::
  2. HTTPHeader

module Net::HTTPHeader

The HTTPHeader module provides access to HTTP headers.

The module is included in:

The headers are a hash-like collection of key/value pairs calledfields.

Request and Response Fields

Headers may be included in:

Exactly which fields should be sent or expected depends on the host; see:

About the Examples

Examples here assume thatnet/http has been required (which also requiresuri):

require'net/http'

Many code examples here use these example websites:

Some examples also assume these variables:

uri =URI('https://jsonplaceholder.typicode.com/')uri.freeze# Examples may not modify.hostname =uri.hostname# => "jsonplaceholder.typicode.com"path =uri.path# => "/"port =uri.port# => 443

So that example requests may be written as:

Net::HTTP.get(uri)Net::HTTP.get(hostname,'/index.html')Net::HTTP.start(hostname)do|http|http.get('/todos/1')http.get('/todos/2')end

An example that needs a modifiedURI first duplicatesuri, then modifies the duplicate:

_uri =uri.dup_uri.path ='/todos/1'

Fields

A header field is a key/value pair.

Field Keys

A field key may be:

Examples:

req =Net::HTTP::Get.new(uri)req[:accept]# => "*/*"req['Accept']# => "*/*"req['ACCEPT']# => "*/*"req['accept'] ='text/html'req[:accept] ='text/html'req['ACCEPT'] ='text/html'

Field Values

A field value may be returned as an array of strings or as a string:

The field value may be set:

Example field values:

Convenience Methods

Various convenience methods retrieve values, set values, query values, set form values, or iterate over fields.

Setters

Method[]= can set any field, but does little to validate the new value; some of the other setter methods provide some validation:

Form Setters

Getters

Method[] can retrieve the value of any field that exists, but always as a string; some of the other getter methods return something different from the simple string value:

Queries

Iterators

Constants

MAX_FIELD_LENGTH
MAX_KEY_LENGTH

Public Instance Methods

Source
# File lib/net/http/header.rb, line 224def[](key)a =@header[key.downcase.to_s]orreturnnila.join(', ')end

Returns the string field value for the case-insensitive fieldkey, ornil if there is no such key; seeFields:

res =Net::HTTP.get_response(hostname,'/todos/1')res['Connection']# => "keep-alive"res['Nosuch']# => nil

Note that some field values may be retrieved via convenience methods; seeGetters.

Source
# File lib/net/http/header.rb, line 240def[]=(key,val)unlessval@header.deletekey.downcase.to_sreturnvalendset_field(key,val)end

Sets the value for the case-insensitivekey toval, overwriting the previous value if the field exists; seeFields:

req =Net::HTTP::Get.new(uri)req['Accept']# => "*/*"req['Accept'] ='text/html'req['Accept']# => "text/html"

Note that some field values may be set via convenience methods; seeSetters.

Source
# File lib/net/http/header.rb, line 261defadd_field(key,val)stringified_downcased_key =key.downcase.to_sif@header.key?(stringified_downcased_key)append_field_value(@header[stringified_downcased_key],val)elseset_field(key,val)endend

Adds valueval to the value array for fieldkey if the field exists; creates the field with the givenkey andval if it does not exist. seeFields:

req =Net::HTTP::Get.new(uri)req.add_field('Foo','bar')req['Foo']# => "bar"req.add_field('Foo','baz')req['Foo']# => "bar, baz"req.add_field('Foo',%w[baz bam])req['Foo']# => "bar, baz, baz, bam"req.get_fields('Foo')# => ["bar", "baz", "baz", "bam"]
Source
# File lib/net/http/header.rb, line 945defbasic_auth(account,password)@header['authorization'] = [basic_encode(account,password)]end

Sets header'Authorization' using the givenaccount andpassword strings:

req.basic_auth('my_account','my_password')req['Authorization']# => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA=="
Alias for:each_capitalized
Source
# File lib/net/http/header.rb, line 654defchunked?returnfalseunless@header['transfer-encoding']field =self['Transfer-Encoding']  (/(?:\A|[^\-\w])chunked(?![\-\w])/i=~field)?true:falseend

Returnstrue if field'Transfer-Encoding' exists and has value'chunked',false otherwise; seeTransfer-Encoding response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['Transfer-Encoding']# => "chunked"res.chunked?# => true
Source
# File lib/net/http/header.rb, line 966defconnection_close?token =/(?:\A|,)\s*close\s*(?:\z|,)/i@header['connection']&.grep(token) {returntrue}@header['proxy-connection']&.grep(token) {returntrue}falseend

Returns whether theHTTP session is to be closed.

Source
# File lib/net/http/header.rb, line 974defconnection_keep_alive?token =/(?:\A|,)\s*keep-alive\s*(?:\z|,)/i@header['connection']&.grep(token) {returntrue}@header['proxy-connection']&.grep(token) {returntrue}falseend

Returns whether theHTTP session is to be kept alive.

Source
# File lib/net/http/header.rb, line 616defcontent_lengthreturnnilunlesskey?('Content-Length')len =self['Content-Length'].slice(/\d+/)orraiseNet::HTTPHeaderSyntaxError,'wrong Content-Length format'len.to_iend

Returns the value of field'Content-Length' as an integer, ornil if there is no such field; seeContent-Length request header:

res =Net::HTTP.get_response(hostname,'/nosuch/1')res.content_length# => 2res =Net::HTTP.get_response(hostname,'/todos/1')res.content_length# => nil
Source
# File lib/net/http/header.rb, line 637defcontent_length=(len)unlesslen@header.delete'content-length'returnnilend@header['content-length'] = [len.to_i.to_s]end

Sets the value of field'Content-Length' to the given numeric; seeContent-Length response header:

_uri =uri.duphostname =_uri.hostname# => "jsonplaceholder.typicode.com"_uri.path ='/posts'# => "/posts"req =Net::HTTP::Post.new(_uri)# => #<Net::HTTP::Post POST>req.body ='{"title": "foo","body": "bar","userId": 1}'req.content_length =req.body.size# => 42req.content_type ='application/json'res =Net::HTTP.start(hostname)do|http|http.request(req)end# => #<Net::HTTPCreated 201 Created readbody=true>
Source
# File lib/net/http/header.rb, line 670defcontent_rangereturnnilunless@header['content-range']m =%r<\A\s*(\w+)\s+(\d+)-(\d+)/(\d+|\*)>.match(self['Content-Range'])orraiseNet::HTTPHeaderSyntaxError,'wrong Content-Range format'returnunlessm[1]=='bytes'm[2].to_i..m[3].to_iend

Returns aRange object representing the value of field'Content-Range', ornil if no such field exists; seeContent-Range response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['Content-Range']# => nilres['Content-Range'] ='bytes 0-499/1000'res['Content-Range']# => "bytes 0-499/1000"res.content_range# => 0..499
Source
# File lib/net/http/header.rb, line 701defcontent_typemain =main_type()returnnilunlessmainsub =sub_type()ifsub"#{main}/#{sub}"elsemainendend

Returns themedia type from the value of field'Content-Type', ornil if no such field exists; seeContent-Type response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['content-type']# => "application/json; charset=utf-8"res.content_type# => "application/json"
Alias for:set_content_type
Source
# File lib/net/http/header.rb, line 453defdelete(key)@header.delete(key.downcase.to_s)end

Removes the header for the given case-insensitivekey (seeFields); returns the deleted value, ornil if no such field exists:

req =Net::HTTP::Get.new(uri)req.delete('Accept')# => ["*/*"]req.delete('Nosuch')# => nil
Alias for:each_header
Source
# File lib/net/http/header.rb, line 484defeach_capitalizedblock_given?orreturnenum_for(__method__) {@header.size }@header.eachdo|k,v|yieldcapitalize(k),v.join(', ')endend

Likeeach_header, but the keys are returned in capitalized form.

Net::HTTPHeader#canonical_each is an alias forNet::HTTPHeader#each_capitalized.

Also aliased as:canonical_each
Source
# File lib/net/http/header.rb, line 417defeach_capitalized_name#:yield: +key+block_given?orreturnenum_for(__method__) {@header.size }@header.each_keydo|k|yieldcapitalize(k)endend

Calls the block with each capitalized field name:

res =Net::HTTP.get_response(hostname,'/todos/1')res.each_capitalized_namedo|key|pkeyifkey.start_with?('C')end

Output:

"Content-Type""Connection""Cache-Control""Cf-Cache-Status""Cf-Ray"

The capitalization is system-dependent; seeCase Mapping.

Returns an enumerator if no block is given.

Source
# File lib/net/http/header.rb, line 364defeach_header#:yield: +key+, +value+block_given?orreturnenum_for(__method__) {@header.size }@header.eachdo|k,va|yieldk,va.join(', ')endend

Calls the block with each key/value pair:

res =Net::HTTP.get_response(hostname,'/todos/1')res.each_headerdo|key,value|p [key,value]ifkey.start_with?('c')end

Output:

["content-type","application/json; charset=utf-8"]["connection","keep-alive"]["cache-control","max-age=43200"]["cf-cache-status","HIT"]["cf-ray","771d17e9bc542cf5-ORD"]

Returns an enumerator if no block is given.

Net::HTTPHeader#each is an alias forNet::HTTPHeader#each_header.

Also aliased as:each
Alias for:each_name
Source
# File lib/net/http/header.rb, line 391defeach_name(&block)#:yield: +key+block_given?orreturnenum_for(__method__) {@header.size }@header.each_key(&block)end

Calls the block with each field key:

res =Net::HTTP.get_response(hostname,'/todos/1')res.each_keydo|key|pkeyifkey.start_with?('c')end

Output:

"content-type""connection""cache-control""cf-cache-status""cf-ray"

Returns an enumerator if no block is given.

Net::HTTPHeader#each_name is an alias forNet::HTTPHeader#each_key.

Also aliased as:each_key
Source
# File lib/net/http/header.rb, line 438defeach_value#:yield: +value+block_given?orreturnenum_for(__method__) {@header.size }@header.each_valuedo|va|yieldva.join(', ')endend

Calls the block with each string field value:

res =Net::HTTP.get_response(hostname,'/todos/1')res.each_valuedo|value|pvalueifvalue.start_with?('c')end

Output:

"chunked""cf-q-config;dur=6.0000002122251e-06""cloudflare"

Returns an enumerator if no block is given.

Source
# File lib/net/http/header.rb, line 341deffetch(key,*args,&block)#:yield: +key+a =@header.fetch(key.downcase.to_s,*args,&block)a.kind_of?(Array)?a.join(', '):aend

With a block, returns the string value forkey if it exists; otherwise returns the value of the block; ignores thedefault_val; seeFields:

res =Net::HTTP.get_response(hostname,'/todos/1')# Field exists; block not called.res.fetch('Connection')do|value|fail'Cannot happen'end# => "keep-alive"# Field does not exist; block called.res.fetch('Nosuch')do|value|value.downcaseend# => "nosuch"

With no block, returns the string value forkey if it exists; otherwise, returnsdefault_val if it was given; otherwise raises an exception:

res.fetch('Connection','Foo')# => "keep-alive"res.fetch('Nosuch','Foo')# => "Foo"res.fetch('Nosuch')# Raises KeyError.
Alias for:set_form_data
Source
# File lib/net/http/header.rb, line 306defget_fields(key)stringified_downcased_key =key.downcase.to_sreturnnilunless@header[stringified_downcased_key]@header[stringified_downcased_key].dupend

Returns the array field value for the givenkey, ornil if there is no such field; seeFields:

res =Net::HTTP.get_response(hostname,'/todos/1')res.get_fields('Connection')# => ["keep-alive"]res.get_fields('Nosuch')# => nil
Source
# File lib/net/http/header.rb, line 463defkey?(key)@header.key?(key.downcase.to_s)end

Returnstrue if the field for the case-insensitivekey exists,false otherwise:

req =Net::HTTP::Get.new(uri)req.key?('Accept')# => truereq.key?('Nosuch')# => false
Source
# File lib/net/http/header.rb, line 723defmain_typereturnnilunless@header['content-type']self['Content-Type'].split(';').first.to_s.split('/')[0].to_s.stripend

Returns the leading (‘type’) part of themedia type from the value of field'Content-Type', ornil if no such field exists; seeContent-Type response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['content-type']# => "application/json; charset=utf-8"res.main_type# => "application"
Source
# File lib/net/http/header.rb, line 956defproxy_basic_auth(account,password)@header['proxy-authorization'] = [basic_encode(account,password)]end

Sets header'Proxy-Authorization' using the givenaccount andpassword strings:

req.proxy_basic_auth('my_account','my_password')req['Proxy-Authorization']# => "Basic bXlfYWNjb3VudDpteV9wYXNzd29yZA=="
Source
# File lib/net/http/header.rb, line 509defrangereturnnilunless@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.5unless/\Abytes=((?:,[ \t]*)*(?:\d+-\d*|-\d+)(?:[ \t]*,(?:[ \t]*\d+-\d*|-\d+)?)*)\z/=~valueraiseNet::HTTPHeaderSyntaxError,"invalid syntax for byte-ranges-specifier: '#{value}'"endbyte_range_set =$1result =byte_range_set.split(/,/).map {|spec|m =/(\d+)?\s*-\s*(\d+)?/i.match(spec)orraiseNet::HTTPHeaderSyntaxError,"invalid byte-range-spec: '#{spec}'"d1 =m[1].to_id2 =m[2].to_iifm[1]andm[2]ifd1>d2raiseNet::HTTPHeaderSyntaxError,"last-byte-pos MUST greater than or equal to first-byte-pos but '#{spec}'"endd1..d2elsifm[1]d1..-1elsifm[2]-d2..-1elseraiseNet::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.ifresult.size==1&&result[0].begin==0&&result[0].end==-1raiseNet::HTTPHeaderSyntaxError,'only one suffix-byte-range-spec with zero suffix-length'endresultend

Returns an array ofRange objects that represent the value of field'Range', ornil if there is no such field; seeRange request header:

req =Net::HTTP::Get.new(uri)req['Range'] ='bytes=0-99,200-299,400-499'req.range# => [0..99, 200..299, 400..499]req.delete('Range')req.range# # => nil
Alias for:set_range
Source
# File lib/net/http/header.rb, line 687defrange_lengthr =content_range()orreturnnilr.end-r.begin+1end

Returns the integer representing length of the value of field'Content-Range', ornil if no such field exists; seeContent-Range response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['Content-Range']# => nilres['Content-Range'] ='bytes 0-499/1000'res.range_length# => 500
Source
# File lib/net/http/header.rb, line 772defset_content_type(type,params = {})@header['content-type'] = [type+params.map{|k,v|"; #{k}=#{v}"}.join('')]end

Sets the value of field'Content-Type'; returns the new value; seeContent-Type request header:

req =Net::HTTP::Get.new(uri)req.set_content_type('application/json')# => ["application/json"]

Net::HTTPHeader#content_type= is an alias forNet::HTTPHeader#set_content_type.

Also aliased as:content_type=
Source
# File lib/net/http/header.rb, line 924defset_form(params,enctype='application/x-www-form-urlencoded',formopt={})@body_data =params@body =nil@body_stream =nil@form_option =formoptcaseenctypewhen/\Aapplication\/x-www-form-urlencoded\z/i,/\Amultipart\/form-data\z/iself.content_type =enctypeelseraiseArgumentError,"invalid enctype: #{enctype}"endend

Stores form data to be used in aPOST orPUT request.

The form data given inparams consists of zero or more fields; each field is:

  • A scalar value.

  • A name/value pair.

  • AnIO stream opened for reading.

Argumentparams should be anEnumerable (methodparams.map will be called), and is often an array or hash.

First, we set up a request:

_uri =uri.dup_uri.path ='/posts'req =Net::HTTP::Post.new(_uri)

Argumentparams As an Array

Whenparams is an array, each of its elements is a subarray that defines a field; the subarray may contain:

  • One string:

    req.set_form([['foo'], ['bar'], ['baz']])
  • Two strings:

    req.set_form([%w[foo 0],%w[bar 1],%w[baz 2]])
  • When argumentenctype (see below) is given as'multipart/form-data':

    • A string name and anIO stream opened for reading:

      require'stringio'req.set_form([['file',StringIO.new('Ruby is cool.')]])
    • A string name, anIO stream opened for reading, and an options hash, which may contain these entries:

      • :filename: The name of the file to use.

      • :content_type: The content type of the uploaded file.

      Example:

      req.set_form([['file', file, {filename: "other-filename.foo"}]]

The various forms may be mixed:

req.set_form(['foo',%w[bar 1], ['file',file]])

Argumentparams As a Hash

Whenparams is a hash, each of its entries is a name/value pair that defines a field:

  • The name is a string.

  • The value may be:

    • nil.

    • Another string.

    • AnIO stream opened for reading (only when argumentenctype – see below – is given as'multipart/form-data').

Examples:

# Nil-valued fields.req.set_form({'foo'=>nil,'bar'=>nil,'baz'=>nil})# String-valued fields.req.set_form({'foo'=>0,'bar'=>1,'baz'=>2})# IO-valued field.require'stringio'req.set_form({'file'=>StringIO.new('Ruby is cool.')})# Mixture of fields.req.set_form({'foo'=>nil,'bar'=>1,'file'=>file})

Optional argumentenctype specifies the value to be given to field'Content-Type', and must be one of:

  • 'application/x-www-form-urlencoded' (the default).

  • 'multipart/form-data'; seeRFC 7578.

Optional argumentformopt is a hash of options (applicable only when argumentenctype is'multipart/form-data') that may include the following entries:

  • :boundary: The value is the boundary string for the multipart message. If not given, the boundary is a random string. SeeBoundary.

  • :charset: Value is the character set for the form submission. Field names and values of non-file fields should be encoded with this charset.

Source
# File lib/net/http/header.rb, line 812defset_form_data(params,sep ='&')query =URI.encode_www_form(params)query.gsub!(/&/,sep)ifsep!='&'self.body =queryself.content_type ='application/x-www-form-urlencoded'end

Sets the request body to a URL-encoded string derived from argumentparams, and sets request header field'Content-Type' to'application/x-www-form-urlencoded'.

The resulting request is suitable forHTTP requestPOST orPUT.

Argumentparams must be suitable for use as argumentenum toURI.encode_www_form.

With only argumentparams given, sets the body to a URL-encoded string with the default separator'&':

req =Net::HTTP::Post.new('example.com')req.set_form_data(q:'ruby',lang:'en')req.body# => "q=ruby&lang=en"req['Content-Type']# => "application/x-www-form-urlencoded"req.set_form_data([['q','ruby'], ['lang','en']])req.body# => "q=ruby&lang=en"req.set_form_data(q: ['ruby','perl'],lang:'en')req.body# => "q=ruby&q=perl&lang=en"req.set_form_data([['q','ruby'], ['q','perl'], ['lang','en']])req.body# => "q=ruby&q=perl&lang=en"

With string argumentsep also given, uses that string as the separator:

req.set_form_data({q:'ruby',lang:'en'},'|')req.body# => "q=ruby|lang=en"

Net::HTTPHeader#form_data= is an alias forNet::HTTPHeader#set_form_data.

Also aliased as:form_data=
Source
# File lib/net/http/header.rb, line 576defset_range(r,e =nil)unlessr@header.delete'range'returnrendr = (r...r+e)ifecaserwhenNumericn =r.to_irangestr = (n>0?"0-#{n-1}":"-#{-n}")whenRangefirst =r.firstlast =r.endlast-=1ifr.exclude_end?iflast==-1rangestr = (first>0?"#{first}-":"-#{-first}")elseraiseNet::HTTPHeaderSyntaxError,'range.first is negative'iffirst<0raiseNet::HTTPHeaderSyntaxError,'range.last is negative'iflast<0raiseNet::HTTPHeaderSyntaxError,'must be .first < .last'iffirst>lastrangestr ="#{first}-#{last}"endelseraiseTypeError,'Range/Integer is required'end@header['range'] = ["bytes=#{rangestr}"]rend

Sets the value for field'Range'; seeRange request header:

With argumentlength:

req =Net::HTTP::Get.new(uri)req.set_range(100)# => 100req['Range']# => "bytes=0-99"

With argumentsoffset andlength:

req.set_range(100,100)# => 100...200req['Range']# => "bytes=100-199"

With argumentrange:

req.set_range(100..199)# => 100..199req['Range']# => "bytes=100-199"

Net::HTTPHeader#range= is an alias forNet::HTTPHeader#set_range.

Also aliased as:range=
Source
# File lib/net/http/header.rb, line 738defsub_typereturnnilunless@header['content-type']_,sub =*self['Content-Type'].split(';').first.to_s.split('/')returnnilunlesssubsub.stripend

Returns the trailing (‘subtype’) part of themedia type from the value of field'Content-Type', ornil if no such field exists; seeContent-Type response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['content-type']# => "application/json; charset=utf-8"res.sub_type# => "json"
Source
# File lib/net/http/header.rb, line 477defto_hash@header.dupend

Returns a hash of the key/value pairs:

req =Net::HTTP::Get.new(uri)req.to_hash# =>{"accept-encoding"=>["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"],"accept"=>["*/*"],"user-agent"=>["Ruby"],"host"=>["jsonplaceholder.typicode.com"]}
Source
# File lib/net/http/header.rb, line 753deftype_paramsresult = {}list =self['Content-Type'].to_s.split(';')list.shiftlist.eachdo|param|k,v =*param.split('=',2)result[k.strip] =v.stripendresultend

Returns the trailing (‘parameters’) part of the value of field'Content-Type', ornil if no such field exists; seeContent-Type response header:

res =Net::HTTP.get_response(hostname,'/todos/1')res['content-type']# => "application/json; charset=utf-8"res.type_params# => {"charset"=>"utf-8"}

Private Instance Methods

Source
# File lib/net/http/header.rb, line 285defappend_field_value(ary,val)casevalwhenEnumerableval.each{|x|append_field_value(ary,x)}elseval =val.to_sif/[\r\n]/n.match?(val.b)raiseArgumentError,'header field value cannot include CR/LF'endary.pushvalendend
Source
# File lib/net/http/header.rb, line 960defbasic_encode(account,password)'Basic '+ ["#{account}:#{password}"].pack('m0')end
Source
# File lib/net/http/header.rb, line 493defcapitalize(name)name.to_s.split('-'.freeze).map {|s|s.capitalize }.join('-'.freeze)end
Source
# File lib/net/http/header.rb, line 270defset_field(key,val)casevalwhenEnumerableary = []append_field_value(ary,val)@header[key.downcase.to_s] =aryelseval =val.to_s# for compatibility use to_s instead of to_strifval.b.count("\r\n")>0raiseArgumentError,'header field value cannot include CR/LF'end@header[key.downcase.to_s] = [val]endend