Permalink
Browse files

Reorganized code that closes the Rack response if needed.

  • Loading branch information...
1 parent fe935d9 commit 127da39097beeb9c9b90212f0139371415185eae @crohr committed Oct 19, 2011
Showing with 29 additions and 25 deletions.
  1. +29 −25 lib/rack/jsonp.rb
View
@@ -13,58 +13,62 @@ def initialize(app, options = {})
@callback_param = options[:callback_param] || 'callback'
end
- # Proxies the request to the application, stripping out the JSON-P callback
- # method and padding the response with the appropriate callback format.
+ # Proxies the request to the application, stripping out the JSON-P
+ # callback method and padding the response with the appropriate callback
+ # format.
#
# Changes nothing if no <tt>callback</tt> param is specified.
#
def call(env)
- # remove the callback and _ parameters BEFORE calling the backend,
- # so that caching middleware does not store a copy for each value of the callback parameter
+ # remove the callback and _ parameters BEFORE calling the backend, so
+ # that caching middleware does not store a copy for each value of the
+ # callback parameter
request = Rack::Request.new(env)
callback = request.params.delete(@callback_param)
- env['QUERY_STRING'] = env['QUERY_STRING'].split("&").delete_if{|param| param =~ /^(_|#{@callback_param})=/}.join("&")
+ env['QUERY_STRING'] = env['QUERY_STRING'].split("&").delete_if{|param|
+ param =~ /^(_|#{@callback_param})=/
+ }.join("&")
- status, headers, app_response = @app.call(env)
- response = if callback && headers['Content-Type'] =~ /json/i
- json = pad(callback, app_response)
- headers['Content-Length'] = json.first.bytesize.to_s
+ status, headers, response = @app.call(env)
+
+ if callback && headers['Content-Type'] =~ /json/i
+ response = pad(callback, response)
+ headers['Content-Length'] = response.first.bytesize.to_s
headers['Content-Type'] = 'application/javascript'
- json
elsif @carriage_return && headers['Content-Type'] =~ /json/i
# add a \n after the response if this is a json (not JSONP) response
- json = carriage_return(app_response)
- headers['Content-Length'] = json.first.bytesize.to_s
- json
- else
- nil
- end
-
- # Close original response if it was Rack::BodyProxy (or anything else responding to close,
- # as we're going to lose it anyway), or it will cause thread failures with newer Rack
- if app_response.respond_to?(:close) && response
- app_response.close
+ response = carriage_return(response)
+ headers['Content-Length'] = response.first.bytesize.to_s
end
- [status, headers, response || app_response]
+ [status, headers, response]
end
# Pads the response with the appropriate callback format according to the
# JSON-P spec/requirements.
#
- # The Rack response spec indicates that it should be enumerable. The method
- # of combining all of the data into a single string makes sense since JSON
- # is returned as a full string.
+ # The Rack response spec indicates that it should be enumerable. The
+ # method of combining all of the data into a single string makes sense
+ # since JSON is returned as a full string.
#
def pad(callback, response, body = "")
response.each{ |s| body << s.to_s }
+ close(response)
["#{callback}(#{body})"]
end
def carriage_return(response, body = "")
response.each{ |s| body << s.to_s }
+ close(response)
["#{body}\n"]
end
+
+ # Close original response if it was Rack::BodyProxy (or anything else
+ # responding to close, as we're going to lose it anyway), or it will cause
+ # thread failures with newer Rack.
+ def close(io)
+ io.close if io.respond_to?(:close)
+ end
end
end

0 comments on commit 127da39

Please sign in to comment.