Class: Rack::JSONR

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/rack/jsonr/jsonr.rb,
lib/rack/jsonr/version.rb

Constant Summary collapse

HTTP_METHODS_TO_OVERRIDE =
%w(HEAD PUT POST DELETE OPTIONS PATCH)
METHOD_OVERRIDE_PARAM_KEY =
'_method'.freeze
HTTP_METHOD_OVERRIDE_HEADER =
'HTTP_X_HTTP_METHOD_OVERRIDE'.freeze
VERSION =
'0.2.8'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ JSONR

Returns a new instance of JSONR.



12
13
14
15
# File 'lib/rack/jsonr/jsonr.rb', line 12

def initialize(app, options={})
  @options = options
  @app = app
end

Class Method Details

.intercept_method_override(env, request, params, override_scope) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rack/jsonr/jsonr.rb', line 48

def self.intercept_method_override(env, request, params, override_scope)
  if is_jsonp_request?(request) or override_scope == :all
    method_override = (params[METHOD_OVERRIDE_PARAM_KEY] || env[HTTP_METHOD_OVERRIDE_HEADER]).to_s.upcase
    if HTTP_METHODS_TO_OVERRIDE.include?(method_override) and !env['rack.jsonr_method_override.original_method']
      env['rack.jsonr_method_override.original_method'] = env['REQUEST_METHOD']
      env['REQUEST_METHOD'] = method_override
      if method_override == 'POST'
        env['rack.request.query_hash'].each do |key,value|
          next if !value.is_a?(Hash)
          next if !value.all? {|k,v| k =~ /^[0-9]+$/ }
          env['rack.request.query_hash'][key] = value.sort.inject([]) {|result, v| result << v[1] }
        end
      end
    end
  end
end

.is_jsonp_request?(request) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/rack/jsonr/jsonr.rb', line 65

def self.is_jsonp_request?(request)
  (request.params.include?('callback') and (request.get? or request.env['rack.jsonr_method_override.original_method'] == 'GET'))
end

Instance Method Details

#call(env) ⇒ Object

Proxies the request to the application, stripping out the JSONP callback method and padding the response with the appropriate callback format if the returned body is application/json

Changes nothing if no callback param is specified.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/rack/jsonr/jsonr.rb', line 23

def call(env)
  status, headers, response = @app.call(env)

  headers = HeaderHash.new(headers)
  request = Rack::Request.new(env)
  params = request.params

  self.class.intercept_method_override(env, request, params, @options[:method_override])

  if is_jsonp_request?(request)
    response = format_jsonp(request.params.delete('callback'), status, headers, response)
    status = 200

    # No longer json, its javascript!
    headers['Content-Type'] = headers['Content-Type'].gsub('json', 'javascript')

    # Set new Content-Length, if it was set before we mutated the response body
    if headers['Content-Length']
      length = response.to_ary.inject(0) { |len, part| len + bytesize(part) }
      headers['Content-Length'] = length.to_s
    end
  end
  [status, headers, response]
end