Skip to content

Commit

Permalink
Merging @mzsanford pull request (Thank you!)
Browse files Browse the repository at this point in the history
Squeezing the force_mime_type method into a *sub!* call

Improving code readability

Making the helper methods and constants *protected*
  • Loading branch information
robertodecurnex committed Sep 12, 2012
1 parent f8c18f1 commit 6181a46
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions lib/rack/jsonp.rb
@@ -1,8 +1,6 @@
module Rack

class JSONP
# Do not allow arbitrary Javascript in the callback.
VALID_CALLBACK_PATTERN = /^[a-zA-Z0-9\._]+$/

def initialize(app)
@app = app
Expand All @@ -13,7 +11,7 @@ def call(env)
requesting_jsonp = Pathname(request.env['PATH_INFO']).extname =~ /^\.jsonp$/i
callback = request.params['callback']

return [400,{},[]] if requesting_jsonp && (!callback || !callback.match(VALID_CALLBACK_PATTERN))
return [400,{},[]] if requesting_jsonp && !self.valid_callback?(callback)

if requesting_jsonp
env['PATH_INFO'].sub!(/\.jsonp/i, '.json')
Expand All @@ -22,21 +20,41 @@ def call(env)

status, headers, body = @app.call(env)

if requesting_jsonp && headers['Content-Type'] && headers['Content-Type'].match(/application\/json/i)
if requesting_jsonp && self.json_response?(headers['Content-Type'])
json = ""
body.each { |s| json << s }
body = ["#{callback}(#{json});"]
headers['Content-Length'] = Rack::Utils.bytesize(body[0]).to_s
headers['Content-Type'] = force_mime_type(headers['Content-Type'], 'application/javascript')
headers['Content-Type'].sub!(/^[^;]+(;?)/, "#{MIME_TYPE}\\1")
end

[status, headers, body]
end

def force_mime_type(content_type, mime_type)
content_type_parts = (content_type || '').split(/;/)
content_type_parts[0] = mime_type
content_type_parts.join(';')
protected

# Do not allow arbitrary Javascript in the callback.
#
# @return [Regexp]
VALID_CALLBACK_PATTERN = /^[a-zA-Z0-9\._]+$/

# @return [String] the JSONP response mime type.
MIME_TYPE = 'application/javascript'

# Checks if the callback function name is safe/valid.
#
# @param [String] callback the string to be used as the JSONP callback function name.
# @return [TrueClass|FalseClass]
def valid_callback?(callback)
!callback.nil? && !callback.match(VALID_CALLBACK_PATTERN).nil?
end

# Check if the response Content Type is JSON.
#
# @param [Hash] content_type the response Content Type
# @return [TrueClass|FalseClass]
def json_response?(content_type)
!content_type.nil? && !content_type.match(/^application\/json/i).nil?
end

end
Expand Down

0 comments on commit 6181a46

Please sign in to comment.