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(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


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

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

#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_body(params) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/httpx/request/body.rb', line 117

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

.initialize_deflater_body(body, encoding) ⇒ Object

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



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

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.



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

def bytesize
  return 0 if @body.nil?

  @body.bytesize
end

#chunk!Object

sets the chunked transfer encoding header.



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

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

#chunked?Boolean

returns whether the chunked transfer encoding header is set.

Returns:

  • (Boolean)


100
101
102
# File 'lib/httpx/request/body.rb', line 100

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

#each(&block) ⇒ Object

consumes and yields the request payload in chunks.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/httpx/request/body.rb', line 49

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)


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

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

  @body.bytesize.zero?
end

#inspectObject

:nocov:



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

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

#rewindObject

if the @body is rewindable, it rewinnds it.



64
65
66
67
68
# File 'lib/httpx/request/body.rb', line 64

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.



86
87
88
89
90
# File 'lib/httpx/request/body.rb', line 86

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)


93
94
95
96
97
# File 'lib/httpx/request/body.rb', line 93

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

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