Skip to content

Commit

Permalink
Added the JSONP middleware and specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
mtodd committed Dec 2, 2008
1 parent 2af2000 commit c8bbdfb
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
38 changes: 38 additions & 0 deletions lib/rack/jsonp.rb
@@ -0,0 +1,38 @@
module Rack

# A Rack middleware for providing JSON-P support.
#
# Full credit to Flinn Mueller (http://actsasflinn.com/) for this contribution.
#
class JSONP

def initialize(app)
@app = app
end

# 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)
status, headers, response = @app.call(env)
request = Rack::Request.new(env)
response = pad(request.params.delete('callback'), response) if request.params.include?('callback')
[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 sinle string makes sense since JSON
# is returned as a full string.
#
def pad(callback, response, body = "")
response.each{ |s| body << s }
"#{callback}(#{body})"
end

end
end
20 changes: 20 additions & 0 deletions test/spec_rack_jsonp.rb
@@ -0,0 +1,20 @@
# require 'rack/mock'
require 'rack/jsonp'

context "Rack::JSONP" do

specify "should wrap the response body in the Javascript callback when provided" do
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, '{"bar":"foo"}'] }
request = Rack::MockRequest.env_for("/", :input => "foo=bar&callback=foo")
body = Rack::JSONP.new(app).call(request).last
body.should == 'foo({"bar":"foo"})'
end

specify "should not change anything if no :callback param is provided" do
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, '{"bar":"foo"}'] }
request = Rack::MockRequest.env_for("/", :input => "foo=bar")
body = Rack::JSONP.new(app).call(request).last
body.should == '{"bar":"foo"}'
end

end

0 comments on commit c8bbdfb

Please sign in to comment.