class Rack::JsonResponseWrapper

Public Class Methods

new(app) click to toggle source
# File lib/rack/json_response_wrapper.rb, line 3
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/json_response_wrapper.rb, line 7
def call(env)
  response = @app.call(env)

  if should_wrap? env, response
    wrap_response(response)
  else
    response
  end
end

Private Instance Methods

should_wrap?(env, response) click to toggle source
# File lib/rack/json_response_wrapper.rb, line 19
def should_wrap?(env, response)
  response_header = response[1]

  if response_header.include? 'Content-Type'
    is_json = response_header['Content-Type'].match(/application\/json/)
    wants_wrap = env.include?('HTTP_X_WRAP_RESPONSE') ||
                 env.include?('X-WRAP-RESPONSE')

    is_json && wants_wrap
  else
    false
  end
end
wrap_response(response) click to toggle source
# File lib/rack/json_response_wrapper.rb, line 33
def wrap_response(response)
  response_header = response[1]

  response_body = ''
  response[2].each do |segment|
    response_body += segment
  end

  response_obj = JSON.parse(response_body)

  wrapped_obj = {
    header: response_header,
    body: response_obj
  }

  # dump JSON to get new content length
  wrapped_body = JSON.dump(wrapped_obj)

  # when we change the content-length, the length will change.
  # therefore, calculate the offset by comparing the length of the old vs. new
  original_content_length = response_header['Content-Length']
  new_content_length = wrapped_body.bytesize
  adjusted_content_length =
    new_content_length.to_s.to_json.bytesize - original_content_length.to_s.to_json.bytesize

  # adjust the new content-length by this offset
  new_content_length += adjusted_content_length

  # set the content length part of the header and redump the JSON
  wrapped_obj[:header]['Content-Length'] = new_content_length.to_s
  wrapped_body = JSON.dump(wrapped_obj)

  wrapped = response.dup
  wrapped[2] = [wrapped_body]

  wrapped
end