Class: XmlNodeStream::HttpStream

Inherits:
Object
  • Object
show all
Defined in:
lib/xml_node_stream/http_stream.rb

Overview

IO-like wrapper for HTTP responses that allows streaming

Constant Summary collapse

DEFAULT_OPEN_TIMEOUT =

Default timeout values in seconds

10
DEFAULT_READ_TIMEOUT =
60
MAX_REDIRECTS =

Maximum number of redirects to follow

5

Instance Method Summary collapse

Constructor Details

#initialize(uri, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT) ⇒ HttpStream

Create a new HttpStream.

Parameters:

  • uri (URI)

    the URI to stream from

  • open_timeout (Integer) (defaults to: DEFAULT_OPEN_TIMEOUT)

    connection timeout in seconds (default 10)

  • read_timeout (Integer) (defaults to: DEFAULT_READ_TIMEOUT)

    read timeout in seconds (default 60)



33
34
35
36
37
38
39
40
41
42
# File 'lib/xml_node_stream/http_stream.rb', line 33

def initialize(uri, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT)
  @uri = uri
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @http = nil
  @buffer = +""
  @eof = false
  @response = nil
  @fiber = nil
end

Instance Method Details

#closevoid

This method returns an undefined value.

Close the stream.



141
142
143
144
145
146
# File 'lib/xml_node_stream/http_stream.rb', line 141

def close
  @http.finish if @http&.started?
rescue
  # Ignore errors during close to ensure cleanup completes
  nil
end

#closed?Boolean

Check if the stream is closed.

Returns:

  • (Boolean)

    true if closed



151
152
153
# File 'lib/xml_node_stream/http_stream.rb', line 151

def closed?
  @http.nil? || !@http.started?
end

#eof?Boolean

Check if at end of file.

Returns:

  • (Boolean)

    true if at EOF



134
135
136
# File 'lib/xml_node_stream/http_stream.rb', line 134

def eof?
  @eof && @buffer.empty?
end

#gets(sep = $/, limit = nil) ⇒ String? Also known as: readline

Read a line from the stream.

Parameters:

  • sep (String, nil) (defaults to: $/)

    the line separator

  • limit (Integer, nil) (defaults to: nil)

    maximum number of bytes to read

Returns:

  • (String, nil)

    the line read, or nil if at EOF



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/xml_node_stream/http_stream.rb', line 97

def gets(sep = $/, limit = nil)
  ensure_response_started

  if sep.nil?
    # Read all
    return read
  end

  sep = sep.to_s

  loop do
    if (idx = @buffer.index(sep))
      line = @buffer.slice!(0, idx + sep.length)
      return line
    end

    break if @eof

    chunk = read_chunk
    if chunk.nil?
      break
    end
    @buffer << chunk
  end

  return nil if @buffer.empty?

  line = @buffer
  @buffer = +""
  line
end

#read(length = nil, outbuf = nil) ⇒ String?

Read data from the stream.

Parameters:

  • length (Integer, nil) (defaults to: nil)

    the number of bytes to read, or nil to read all

  • outbuf (String, nil) (defaults to: nil)

    optional output buffer

Returns:

  • (String, nil)

    the data read, or nil if at EOF



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/xml_node_stream/http_stream.rb', line 49

def read(length = nil, outbuf = nil)
  ensure_response_started

  if length.nil?
    # Read all remaining data
    result = @buffer.dup
    while (chunk = read_chunk)
      result << chunk
    end
    @buffer = +""
    if outbuf
      outbuf.replace(result)
      outbuf
    else
      result
    end
  else
    # Read specific length
    while @buffer.bytesize < length && !@eof
      chunk = read_chunk
      break if chunk.nil?
      @buffer << chunk
    end

    if @buffer.bytesize >= length
      result = @buffer.byteslice(0, length)
      @buffer = @buffer.byteslice(length..-1) || +""
    else
      result = @buffer.dup
      @buffer = +""
    end

    if result.empty? && @eof
      nil
    elsif outbuf
      outbuf.replace(result)
      outbuf
    else
      result
    end
  end
end

#to_ioHttpStream

Return self as the IO object for REXML compatibility.

Returns:



158
159
160
# File 'lib/xml_node_stream/http_stream.rb', line 158

def to_io
  self
end