Class: HTTPX::Request::Body

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/httpx/request/body.rb

Overview

Implementation of the HTTP Request body as a delegator which iterates (responds to each) payload chunks.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(headers, options, body: nil, form: nil, json: nil, xml: nil, **params) ⇒ Body

inits the instance with the request headers, options and params, which contain the payload definition. it wraps the given body with the appropriate encoder on initialization.

..., json: { foo: "bar" }) #=> json encoder
..., form: { foo: "bar" }) #=> form urlencoded encoder
..., form: { foo: Pathname.open("path/to/file") }) #=> multipart urlencoded encoder
..., form: { foo: File.open("path/to/file") }) #=> multipart urlencoded encoder
..., form: { body: "bla") }) #=> raw data encoder


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/httpx/request/body.rb', line 28

def initialize(headers, options, body: nil, form: nil, json: nil, xml: nil, **params)
  @headers = headers
  @options = options.merge(params)

  @body = if body
    Transcoder::Body.encode(body)
  elsif form
    Transcoder::Form.encode(form)
  elsif json
    Transcoder::JSON.encode(json)
  elsif xml
    Transcoder::Xml.encode(xml)
  end

  if @body
    if @options.compress_request_body && @headers.key?("content-encoding")

      @headers.get("content-encoding").each do |encoding|
        @body = self.class.initialize_deflater_body(@body, encoding)
      end
    end

    @headers["content-type"] ||= @body.content_type
    @headers["content-length"] = @body.bytesize unless unbounded_body?
  end

  super(@body)
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options.



18
19
20
# File 'lib/httpx/request/body.rb', line 18

def options
  @options
end

Class Method Details

.initialize_deflater_body(body, encoding) ⇒ Object

returns the body wrapped with the correct deflater accordinng to the given encodisng.



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/httpx/request/body.rb', line 127

def initialize_deflater_body(body, encoding)
  case encoding
  when "gzip"
    Transcoder::GZIP.encode(body)
  when "deflate"
    Transcoder::Deflate.encode(body)
  when "identity"
    body
  else
    body
  end
end

.new(_, options, body: nil, **params) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'lib/httpx/request/body.rb', line 7

def new(_, options, body: nil, **params)
  if body.is_a?(self)
    # request derives its options from body
    body.options = options.merge(params)
    return body
  end

  super
end

Instance Method Details

#bytesizeObject

returns the @body payload size in bytes.



88
89
90
91
92
# File 'lib/httpx/request/body.rb', line 88

def bytesize
  return 0 if @body.nil?

  @body.bytesize
end

#chunk!Object

sets the chunked transfer encoding header.



114
115
116
# File 'lib/httpx/request/body.rb', line 114

def chunk!
  @headers.add("transfer-encoding", "chunked")
end

#chunked?Boolean

returns whether the chunked transfer encoding header is set.

Returns:

  • (Boolean)


109
110
111
# File 'lib/httpx/request/body.rb', line 109

def chunked?
  @headers["transfer-encoding"] == "chunked"
end

#each(&block) ⇒ Object

consumes and yields the request payload in chunks.



58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/httpx/request/body.rb', line 58

def each(&block)
  return enum_for(__method__) unless block
  return if @body.nil?

  body = stream(@body)
  if body.respond_to?(:read)
    ::IO.copy_stream(body, ProcIO.new(block))
  elsif body.respond_to?(:each)
    body.each(&block)
  else
    block[body.to_s]
  end
end

#empty?Boolean

return true if the body has been fully drained (or does nnot exist).

Returns:

  • (Boolean)


80
81
82
83
84
85
# File 'lib/httpx/request/body.rb', line 80

def empty?
  return true if @body.nil?
  return false if chunked?

  @body.bytesize.zero?
end

#inspectObject

:nocov:



119
120
121
122
# File 'lib/httpx/request/body.rb', line 119

def inspect
  "#<HTTPX::Request::Body:#{object_id} " \
    "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
end

#rewindObject

if the @body is rewindable, it rewinnds it.



73
74
75
76
77
# File 'lib/httpx/request/body.rb', line 73

def rewind
  return if empty?

  @body.rewind if @body.respond_to?(:rewind)
end

#stream(body) ⇒ Object

sets the body to yield using chunked trannsfer encoding format.



95
96
97
98
99
# File 'lib/httpx/request/body.rb', line 95

def stream(body)
  return body unless chunked?

  Transcoder::Chunker.encode(body.enum_for(:each))
end

#unbounded_body?Boolean

returns whether the body yields infinitely.

Returns:

  • (Boolean)


102
103
104
105
106
# File 'lib/httpx/request/body.rb', line 102

def unbounded_body?
  return @unbounded_body if defined?(@unbounded_body)

  @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY)
end