Class: ReactOnRailsPro::StreamRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/react_on_rails_pro/stream_request.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&request_block) ⇒ StreamRequest

Returns a new instance of StreamRequest.



86
87
88
# File 'lib/react_on_rails_pro/stream_request.rb', line 86

def initialize(&request_block)
  @request_executor = request_block
end

Class Method Details

.create(&request_block) ⇒ Object

Method to start the decoration



142
143
144
# File 'lib/react_on_rails_pro/stream_request.rb', line 142

def self.create(&request_block)
  StreamDecorator.new(new(&request_block))
end

Instance Method Details

#each_chunk(&block) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/react_on_rails_pro/stream_request.rb', line 92

def each_chunk(&block)
  return enum_for(:each_chunk) unless block

  send_bundle = false
  error_body = +""
  loop do
    stream_response = @request_executor.call(send_bundle)

    # Chunks can be merged during streaming, so we separate them by newlines
    # Also, we check the status code inside the loop block because calling `status` outside the loop block
    # is blocking, it will wait for the response to be fully received
    # Look at the spec of `status` in `spec/react_on_rails_pro/stream_spec.rb` for more details
    process_response_chunks(stream_response, error_body, &block)
    break
  rescue HTTPX::HTTPError => e
    send_bundle = handle_http_error(e, error_body, send_bundle)
  rescue HTTPX::ReadTimeoutError => e
    raise ReactOnRailsPro::Error, "Time out error while server side render streaming a component.\n" \
                                  "Original error:\n#{e}\n#{e.backtrace}"
  end
end

#handle_http_error(error, error_body, send_bundle) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/react_on_rails_pro/stream_request.rb', line 126

def handle_http_error(error, error_body, send_bundle)
  response = error.response
  case response.status
  when ReactOnRailsPro::STATUS_SEND_BUNDLE
    # To prevent infinite loop
    ReactOnRailsPro::Error.raise_duplicate_bundle_upload_error if send_bundle

    true
  when ReactOnRailsPro::STATUS_INCOMPATIBLE
    raise ReactOnRailsPro::Error, error_body
  else
    raise ReactOnRailsPro::Error, "Unexpected response code from renderer: #{response.status}:\n#{error_body}"
  end
end

#process_response_chunks(stream_response, error_body) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/react_on_rails_pro/stream_request.rb', line 114

def process_response_chunks(stream_response, error_body)
  loop_response_lines(stream_response) do |chunk|
    if stream_response.is_a?(HTTPX::ErrorResponse) || stream_response.status >= 400
      error_body << chunk
      next
    end

    processed_chunk = chunk.strip
    yield processed_chunk unless processed_chunk.empty?
  end
end