class Racknga::Middleware::JSONP
This is a middleware that provides JSONP
support.
If you use this middleware, your Rack application just returns JSON response.
Usage:
require "racknga" use Rack::ContentLength use Racknga::Middleware::JSONP json_application = Proc.new do |env| [200, {"Content-Type" => "application/json"}, ['{"Hello": "World"}']] end run json_application
Results:
% curl 'http://localhost:9292/' {"Hello": "World"} % curl 'http://localhost:9292/?callback=function' function({"Hello": "World"})
You can use this middleware with Racknga::Middleware::Cache
. You should use this middleware before the cache middleware:
use Racknga::Middleawre::JSONP use Racknga::Middleawre::Cache, :database_path => "var/cache/db" run YourApplication
If you use this middleware after the cache middleware, the cache middleware will cache many responses that just only differ callback parameter value. Here are examples:
Recommended case:
use Racknga::Middleawre::JSONP use Racknga::Middleawre::Cache, :database_path => "var/cache/db" run YourApplication
Requests:
http://localhost:9292/ -> no cache. cached. http://localhost:9292/?callback=function1 -> use cache. http://localhost:9292/?callback=function2 -> use cache. http://localhost:9292/?callback=function3 -> use cache. http://localhost:9292/?callback=function1 -> use cache.
Not recommended case:
use Racknga::Middleawre::Cache, :database_path => "var/cache/db" use Racknga::Middleawre::JSONP run YourApplication
Requests:
http://localhost:9292/ -> no cache. cached. http://localhost:9292/?callback=function1 -> no cache. cached. http://localhost:9292/?callback=function2 -> no cache. cached. http://localhost:9292/?callback=function3 -> no cache. cached. http://localhost:9292/?callback=function1 -> use cache.
Public Class Methods
new(application)
click to toggle source
# File lib/racknga/middleware/jsonp.rb, line 79 def initialize(application) @application = application end
Public Instance Methods
call(environment)
click to toggle source
For Rack.
# File lib/racknga/middleware/jsonp.rb, line 84 def call(environment) request = Rack::Request.new(environment) callback = request["callback"] update_cache_key(request) if callback status, headers, body = @application.call(environment) return [status, headers, body] unless callback header_hash = Rack::Utils::HeaderHash.new(headers) return [status, headers, body] unless json_response?(header_hash) body = Writer.new(callback, body) update_content_type(header_hash) [status, header_hash, body] end
Private Instance Methods
json_response?(header_hash)
click to toggle source
# File lib/racknga/middleware/jsonp.rb, line 116 def json_response?(header_hash) content_type = header_hash["Content-Type"] media_type = content_type.split(/\s*;\s*/, 2).first.downcase media_type == "application/json" or media_type == "application/javascript" or media_type == "text/javascript" end
update_cache_key(request)
click to toggle source
# File lib/racknga/middleware/jsonp.rb, line 98 def update_cache_key(request) return unless Middleware.const_defined?(:Cache) cache_key = Cache::KEY path = request.fullpath path, parameters = path.split(/\?/, 2) if parameters parameters = parameters.split(/[&;]/).reject do |parameter| key, value = parameter.split(/\=/, 2) key == "callback" or (key == "_" and value = /\A\d+\z/) end.join("&") path << "?" << parameters unless parameters.empty? end key = request.env[cache_key] request.env[cache_key] = [key, path].compact.join(":") end
update_content_type(header_hash)
click to toggle source
# File lib/racknga/middleware/jsonp.rb, line 124 def update_content_type(header_hash) content_type = header_hash["Content-Type"] media_type, parameters = content_type.split(/\s*;\s*/, 2) _ = media_type # FIXME: suppress a warning. :< # We should use application/javascript not # text/javascript when all IE <= 8 are deprecated. :< updated_content_type = ["text/javascript", parameters].compact.join("; ") header_hash["Content-Type"] = updated_content_type end