Class: HTTPX::Request::Body

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

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(h, options, **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

Parameters:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/httpx/request/body.rb', line 31

def initialize(h, options, **params)
  @headers = h
  @body = self.class.initialize_body(params)
  @options = options.merge(params)

  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

#optionsOptions

Returns the value of attribute options.

Returns:



21
22
23
# File 'lib/httpx/request/body.rb', line 21

def options
  @options
end

Class Method Details

.initialize_body(params) ⇒ body_encoder?

Parameters:

  • params (Hash[Symbol, untyped])

Returns:

  • (body_encoder, nil)


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/httpx/request/body.rb', line 128

def initialize_body(params)
  if (body = params.delete(:body))
    # @type var body: bodyIO
    Transcoder::Body.encode(body)
  elsif (form = params.delete(:form))
    if Transcoder::Multipart.multipart?(form)
      # @type var form: Transcoder::Multipart::multipart_input
      Transcoder::Multipart.encode(form)
    else
      # @type var form: Transcoder::urlencoded_input
      Transcoder::Form.encode(form)
    end
  elsif (json = params.delete(:json))
    # @type var body: _ToJson
    Transcoder::JSON.encode(json)
  end
end

.initialize_deflater_body(body, encoding) ⇒ body_encoder

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

Parameters:

  • body (body_encoder)
  • encoding (Encoding, String)

Returns:

  • (body_encoder)


147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/httpx/request/body.rb', line 147

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(h, options, body: nil, **params) ⇒ Object



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

def new(h, options, body: nil, **params)
  case body
  when self
    # request derives its options from body
    body.options = options.merge(params)
    body
  when nil
    super(h, options, **params)
  else
    super
  end
end

Instance Method Details

#bytesizeInteger, Float

returns the @body payload size in bytes.

Returns:

  • (Integer, Float)


90
91
92
93
94
# File 'lib/httpx/request/body.rb', line 90

def bytesize
  return 0 if @body.nil?

  @body.bytesize
end

#chunk!void

This method returns an undefined value.

sets the chunked transfer encoding header.



116
117
118
# File 'lib/httpx/request/body.rb', line 116

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

#chunked?Boolean

returns whether the chunked transfer encoding header is set.

Returns:

  • (Boolean)


111
112
113
# File 'lib/httpx/request/body.rb', line 111

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

#closeObject



70
71
72
# File 'lib/httpx/request/body.rb', line 70

def close
  @body.close if @body.respond_to?(:close)
end

#eachvoid #eachEnumerable[String]

consumes and yields the request payload in chunks.

Overloads:

  • #eachvoid

    This method returns an undefined value.

  • #eachEnumerable[String]

    Returns:

    • (Enumerable[String])

Yields:

Yield Parameters:

  • arg0 (String)

Yield Returns:

  • (void)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/httpx/request/body.rb', line 52

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

  body = stream(@body)
  if body.respond_to?(:read)
    while (chunk = body.read(16_384))
      block.call(chunk)
    end
    # TODO: use copy_stream once bug is resolved: https://bugs.ruby-lang.org/issues/21131
    # 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)


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

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

  @body.bytesize.zero?
end

#inspectObject

simplecov:disable



121
122
123
124
# File 'lib/httpx/request/body.rb', line 121

def inspect
  "#<#{self.class}:#{object_id} " \
    "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
end

#rewindvoid

This method returns an undefined value.

if the @body is rewindable, it rewinnds it.



75
76
77
78
79
# File 'lib/httpx/request/body.rb', line 75

def rewind
  return if empty?

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

#stream(body) ⇒ bodyIO

sets the body to yield using chunked trannsfer encoding format.

Parameters:

Returns:

  • (bodyIO)


97
98
99
100
101
# File 'lib/httpx/request/body.rb', line 97

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)


104
105
106
107
108
# File 'lib/httpx/request/body.rb', line 104

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

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