class Rack::JSONP
A Rack middleware for providing JSON-P support.
Adapted from Flinn Mueller (actsasflinn.com/).
Public Class Methods
new(app, options = {})
click to toggle source
# File lib/rack/jsonp.rb, line 10 def initialize(app, options = {}) @app = app @carriage_return = options[:carriage_return] || false @callback_param = options[:callback_param] || 'callback' @timestamp_param = options[:timestamp_param] || '_' end
Public Instance Methods
call(env)
click to toggle source
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 callback
param is specified.
# File lib/rack/jsonp.rb, line 23 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 request = Rack::Request.new(env) callback = request.params.delete(@callback_param) timestamp = request.params.delete(@timestamp_param) env['QUERY_STRING'] = env['QUERY_STRING'].split("&").delete_if{|param| param =~ /^(#{@timestamp_param}|#{@callback_param})=/ }.join("&") env['rack.jsonp.callback'] = callback env['rack.jsonp.timestamp'] = timestamp 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' elsif @carriage_return && headers['Content-Type'] =~ /json/i # add a \n after the response if this is a json (not JSONP) response response = carriage_return(response) headers['Content-Length'] = response.first.bytesize.to_s end [status, headers, response] end
carriage_return(response, body = "")
click to toggle source
# File lib/rack/jsonp.rb, line 64 def carriage_return(response, body = "") response.each{ |s| body << s.to_s } close(response) ["#{body}\n"] end
close(io)
click to toggle source
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.
# File lib/rack/jsonp.rb, line 73 def close(io) io.close if io.respond_to?(:close) end
pad(callback, response, body = "")
click to toggle source
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.
# File lib/rack/jsonp.rb, line 58 def pad(callback, response, body = "") response.each{ |s| body << s.to_s } close(response) ["#{callback}(#{body})"] end