From 839ee0e3842ecfb910b6d08814c4100d4ca1104b Mon Sep 17 00:00:00 2001 From: Steven Mohapi-Banks Date: Fri, 10 Jun 2011 17:07:43 +0100 Subject: [PATCH 1/2] Moved Fiber creation up to the Goliath::Request.process layer to enable async middleware to make Fiber-aware aynchronous calls during pre-processing --- lib/goliath/api.rb | 40 +++++++++++++++++++--------------------- lib/goliath/request.rb | 34 ++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/lib/goliath/api.rb b/lib/goliath/api.rb index 2cfe1c4a..b16f52ba 100644 --- a/lib/goliath/api.rb +++ b/lib/goliath/api.rb @@ -153,30 +153,28 @@ def method_missing(name, *args, &blk) # @param env [Goliath::Env] The request environment # @return [Goliath::Connection::AsyncResponse] An async response. def call(env) - Fiber.new { - begin - Thread.current[GOLIATH_ENV] = env - status, headers, body = response(env) - - if status - if body == Goliath::Response::STREAMING - env[STREAM_START].call(status, headers) - else - env[ASYNC_CALLBACK].call([status, headers, body]) - end + begin + Thread.current[GOLIATH_ENV] = env + status, headers, body = response(env) + + if status + if body == Goliath::Response::STREAMING + env[STREAM_START].call(status, headers) + else + env[ASYNC_CALLBACK].call([status, headers, body]) end + end - rescue Goliath::Validation::Error => e - env[RACK_EXCEPTION] = e - env[ASYNC_CALLBACK].call(validation_error(e.status_code, e.message)) + rescue Goliath::Validation::Error => e + env[RACK_EXCEPTION] = e + env[ASYNC_CALLBACK].call(validation_error(e.status_code, e.message)) - rescue Exception => e - env.logger.error(e.message) - env.logger.error(e.backtrace.join("\n")) - env[RACK_EXCEPTION] = e - env[ASYNC_CALLBACK].call(validation_error(500, e.message)) - end - }.resume + rescue Exception => e + env.logger.error(e.message) + env.logger.error(e.backtrace.join("\n")) + env[RACK_EXCEPTION] = e + env[ASYNC_CALLBACK].call(validation_error(500, e.message)) + end Goliath::Connection::AsyncResponse end diff --git a/lib/goliath/request.rb b/lib/goliath/request.rb index cd854e7a..6bff41e6 100644 --- a/lib/goliath/request.rb +++ b/lib/goliath/request.rb @@ -128,13 +128,15 @@ def close # # @return [Nil] def process - begin - @state = :finished - @env['rack.input'].rewind if @env['rack.input'] - post_process(@app.call(@env)) - rescue Exception => e - server_exception(e) - end + Fiber.new { + begin + @state = :finished + @env['rack.input'].rewind if @env['rack.input'] + post_process(@app.call(@env)) + rescue Exception => e + server_exception(e) + end + }.resume end # Invoked by the app / middleware once the request @@ -166,10 +168,10 @@ def post_process(results) @response.status, @response.headers, @response.body = status, headers, body @response.each { |chunk| @conn.send_data(chunk) } @env[RACK_LOGGER].info("Status: #{@response.status}, " + - "Content-Length: #{@response.headers['Content-Length']}, " + - "Response Time: #{"%.2f" % ((Time.now.to_f - @env[:start_time]) * 1000)}ms") + "Content-Length: #{@response.headers['Content-Length']}, " + + "Response Time: #{"%.2f" % ((Time.now.to_f - @env[:start_time]) * 1000)}ms") - @conn.terminate_request(keep_alive) + @conn.terminate_request(keep_alive) rescue Exception => e server_exception(e) end @@ -206,13 +208,13 @@ def keep_alive case @env[HTTP_VERSION] # HTTP 1.1: all requests are persistent requests, client # must send a Connection:close header to indicate otherwise - when '1.1' then - (@env[HTTP_PREFIX + CONNECTION].downcase != 'close') rescue true + when '1.1' then + (@env[HTTP_PREFIX + CONNECTION].downcase != 'close') rescue true - # HTTP 1.0: all requests are non keep-alive, client must - # send a Connection: Keep-Alive to indicate otherwise - when '1.0' then - (@env[HTTP_PREFIX + CONNECTION].downcase == 'keep-alive') rescue false + # HTTP 1.0: all requests are non keep-alive, client must + # send a Connection: Keep-Alive to indicate otherwise + when '1.0' then + (@env[HTTP_PREFIX + CONNECTION].downcase == 'keep-alive') rescue false end end end From 49ab8c7452a5b1d989d91dd5031812dd82521797 Mon Sep 17 00:00:00 2001 From: Steven Mohapi-Banks Date: Wed, 22 Jun 2011 00:02:19 +0100 Subject: [PATCH 2/2] Pulled in the indifferent_params method from Sinatra so that params can be indexed with Symbols --- lib/goliath/rack/params.rb | 16 +++++++++++++++- spec/unit/rack/params_spec.rb | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/goliath/rack/params.rb b/lib/goliath/rack/params.rb index 2ac1dd04..03d42939 100644 --- a/lib/goliath/rack/params.rb +++ b/lib/goliath/rack/params.rb @@ -58,8 +58,22 @@ def retrieve_params(env) params.merge!(post_params) end - params + indifferent_params(params) end + + def indifferent_params(params) + params = indifferent_hash.merge(params) + params.each do |key, value| + next unless value.is_a?(Hash) + params[key] = indifferent_params(value) + end + end + + # Creates a Hash with indifferent access. + def indifferent_hash + Hash.new {|hash,key| hash[key.to_s] if Symbol === key } + end + end end end diff --git a/spec/unit/rack/params_spec.rb b/spec/unit/rack/params_spec.rb index 749a9159..b8ddfd0f 100644 --- a/spec/unit/rack/params_spec.rb +++ b/spec/unit/rack/params_spec.rb @@ -19,6 +19,7 @@ ret = @params.retrieve_params(@env) ret['foo'].should == 'bar' + ret[:foo].should == 'bar' ret['baz'].should == 'bonkey' end @@ -38,6 +39,8 @@ ret['foo'].should == 'bar' ret['baz'].should == 'bonkey' ret['zonk'].should == {'donk' => 'monk'} + ret[:zonk].should == {'donk' => 'monk'} + ret[:zonk][:donk].should == 'monk' end it 'parses arrays of data' do @@ -47,6 +50,7 @@ ret['foo'].is_a?(Array).should be_true ret['foo'].length.should == 3 ret['foo'].should == %w(bar baz foos) + ret[:foo].should == %w(bar baz foos) end it 'parses multipart data' do @@ -67,6 +71,7 @@ ret = @params.retrieve_params(@env) ret['submit-name'].should == 'Larry' + ret[:"submit-name"].should == 'Larry' ret['submit-name-with-content'].should == 'Berry' end @@ -140,6 +145,7 @@ ret = @params.retrieve_params(@env) ret['foo'].should == 'bar' + ret[:foo].should == 'bar' end it "handles empty input gracefully on JSON" do