From b5c0fcd5eff6a703925c3fa453643ebbbabaf63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janko=20Marohni=C4=87?= Date: Wed, 23 May 2018 15:42:21 +0200 Subject: [PATCH] Stop sending response data if connection is closed If the connection has been closed, there is no point in continuing iterating over the response body and continuing to send data, because it will never get written to the socket anyway. This saves on performance. Also, once `#close` has been called on the response body, continuing to iterate over it might raise an exception. Imagine a scenario where the body is a lazy enumerable that retrieves chunks from an open file, and `#close` closes the file. --- lib/goliath/request.rb | 3 ++- lib/goliath/response.rb | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/goliath/request.rb b/lib/goliath/request.rb index 816aaed0..2e7606d0 100644 --- a/lib/goliath/request.rb +++ b/lib/goliath/request.rb @@ -214,8 +214,9 @@ def post_process(results) # Writes each chunk of the response data in a new tick. This achieves # streaming, because EventMachine flushes the sent data to the socket at - # the end of each tick. + # the end of each tick. Stops sending data if connection has been closed. def stream_data(chunks, &block) + return if @response.closed? @conn.send_data(chunks.next) EM.next_tick { stream_data(chunks, &block) } rescue StopIteration diff --git a/lib/goliath/response.rb b/lib/goliath/response.rb index 37b0e8cb..69b6ca1b 100644 --- a/lib/goliath/response.rb +++ b/lib/goliath/response.rb @@ -28,6 +28,7 @@ class Response def initialize @headers = Goliath::Headers.new @status = 200 + @closed = false end # Creates the header line for the response @@ -72,6 +73,14 @@ def headers=(key_value_pairs) # @return [Nil] def close body.close if body.respond_to?(:close) + @closed = true + end + + # Returns whether the response has been closed + # + # @return [Boolean] + def closed? + @closed end # Yields each portion of the response