Class: Rack::JSONParser

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/json_parser.rb

Overview

Rack middleware which transforms JSON during the request and response. Configurable so request/response processing can be turned off if desired. Only transforms if the Content-Type header is set and includes ‘application/json’. This allows for several types of response content to be served by the application without interference by this middleware. This however requires the client and app to set the ‘Content-Type’ correctly.

Constant Summary collapse

CONTENT_TYPE_KEY =
'Content-Type'.freeze
CONTENT_TYPE_ALT_KEY =
'CONTENT_TYPE'.freeze
CONTENT_LENGTH_KEY =
'Content-Length'.freeze
CONTENT_TYPE_JSON =
'application/json'.freeze
ENV_PAYLOAD_KEY =
'request.payload'.freeze
ENV_RACK_INPUT_KEY =
'rack.input'.freeze

Instance Method Summary collapse

Constructor Details

#initialize(app, transform_request: true, transform_response: true) ⇒ JSONParser

Called via the rack ‘use` method. Used to register the middleware and optionally toggle request and response processing of JSON to Object. By default both the request and response is processed and transformed.



24
25
26
27
28
# File 'lib/rack/json_parser.rb', line 24

def initialize(app, transform_request: true, transform_response: true)
  @app = app
  @transform_request = transform_request
  @transform_response = transform_response
end

Instance Method Details

#call(env) ⇒ Object

Loads the request JSON string into a Hash instance. Expects the app response body to be an object e.g. Hash, putting the object in an array will likely cause unexpected JSON. If the response body is processed then the ‘Content-Length` header will be set to the body#length.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rack/json_parser.rb', line 35

def call(env)
  env = Rack::Utils::HeaderHash.new(env)

  if transform_request?(env)
    env[ENV_PAYLOAD_KEY] = Oj.load(env[ENV_RACK_INPUT_KEY])
  end

  status, headers, body = @app.call(env)
  headers = Rack::Utils::HeaderHash.new(headers)

  if transform_response?(headers, body)
    body = Oj.dump(body) unless body.is_a?(String)
    headers[CONTENT_LENGTH_KEY] = body.length.to_s
    body = [body] unless body.respond_to?(:each)
  end

  [status, headers, body]
end