Class: HTTP::Request::Body

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

Overview

Represents an HTTP request body with streaming support

Direct Known Subclasses

Features::AutoDeflate::CompressedBody

Defined Under Namespace

Classes: ProcIO

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ HTTP::Request::Body

Initialize a new request body

Examples:

Body.new("hello world")

Parameters:

  • source (Object)


23
24
25
26
27
# File 'lib/http/request/body.rb', line 23

def initialize(source)
  @source = source

  validate_source_type!
end

Instance Attribute Details

#sourceString, ... (readonly)

The source data for this body

Examples:

body.source # => "hello world"

Returns:

  • (String, Enumerable, IO, nil)


14
15
16
# File 'lib/http/request/body.rb', line 14

def source
  @source
end

Instance Method Details

#==(other) ⇒ Boolean

Check equality based on source

Examples:

body == other_body

Parameters:

  • other (Object)

Returns:

  • (Boolean)


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

def ==(other)
  other.is_a?(self.class) && source == other.source
end

#eachself #eachEnumerator[String, self]

Yields chunks of content to be streamed

Examples:

body.each { |chunk| socket.write(chunk) }

Overloads:

  • #eachself

    Returns:

    • (self)
  • #eachEnumerator[String, self]

    Returns:

    • (Enumerator[String, self])

Yields:

Yield Parameters:

  • (String)
  • arg0 (String)

Yield Returns:

  • (void)

Returns:

  • (self)


89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/http/request/body.rb', line 89

def each(&block)
  if @source.is_a?(String)
    yield @source
  elsif @source.respond_to?(:read)
    IO.copy_stream(@source, ProcIO.new(block))
    rewind(@source)
  elsif @source
    @source.each(&block)
  end

  self
end

#empty?Boolean

Whether the body is empty

Examples:

body.empty? # => true

Returns:

  • (Boolean)


36
37
38
# File 'lib/http/request/body.rb', line 36

def empty?
  @source.nil?
end

#loggable?Boolean

Whether the body content can be accessed for logging

Returns true for String sources (the content can be inspected). Returns false for IO streams and Enumerables (which cannot be read without consuming them), and for nil bodies.

The logging feature checks the string encoding separately to decide whether to log the content as text or format it as binary.

Examples:

body.loggable? # => true

Returns:

  • (Boolean)


54
55
56
# File 'lib/http/request/body.rb', line 54

def loggable?
  @source.is_a?(String)
end

#rewind(io) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Rewind an IO source if possible

Parameters:

  • io (Object)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/http/request/body.rb', line 118

def rewind(io)
  io.rewind if io.respond_to? :rewind
rescue Errno::ESPIPE, Errno::EPIPE
  # Pipe IOs respond to `:rewind` but fail when you call it.
  #
  # Calling `IO#rewind` on a pipe, fails with *ESPIPE* on MRI,
  # but *EPIPE* on jRuby.
  #
  # - **ESPIPE** -- "Illegal seek."
  #   Invalid seek operation (such as on a pipe).
  #
  # - **EPIPE** -- "Broken pipe."
  #   There is no process reading from the other end of a pipe. Every
  #   library function that returns this error code also generates
  #   a SIGPIPE signal; this signal terminates the program if not handled
  #   or blocked. Thus, your program will never actually see EPIPE unless
  #   it has handled or blocked SIGPIPE.
  #
  # See: https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html
  nil
end

#sizeInteger

Returns size for the "Content-Length" header

Examples:

body.size

Returns:

  • (Integer)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/http/request/body.rb', line 65

def size
  if @source.is_a?(String)
    @source.bytesize
  elsif @source.respond_to?(:read)
    raise RequestError, "IO object must respond to #size" unless @source.respond_to?(:size)

    @source.size
  elsif @source.nil?
    0
  else
    raise RequestError,
          "cannot determine size of body: #{@source.inspect}; " \
          "set the Content-Length header explicitly or use chunked Transfer-Encoding"
  end
end

#validate_source_type!void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Validate that source is a supported type

Raises:



143
144
145
146
147
148
149
150
# File 'lib/http/request/body.rb', line 143

def validate_source_type!
  return if @source.is_a?(String)
  return if @source.respond_to?(:read)
  return if @source.is_a?(Enumerable)
  return if @source.nil?

  raise RequestError, "body of wrong type: #{@source.class}"
end