Class: Securial::Middleware::TransformRequestKeys

Inherits:
Object
  • Object
show all
Defined in:
lib/securial/middleware/transform_request_keys.rb

Overview

Rack middleware that transforms JSON request body keys to snake_case.

This middleware enables Rails applications to accept camelCase JSON from frontend applications while automatically converting keys to Ruby’s snake_case convention before they reach the application.

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ TransformRequestKeys

Initializes the middleware with the Rack application.

Examples:

middleware = TransformRequestKeys.new(app)

Parameters:

  • app (#call)

    The Rack application to wrap



40
41
42
# File 'lib/securial/middleware/transform_request_keys.rb', line 40

def initialize(app)
  @app = app
end

Instance Method Details

#call(env) ⇒ Array

Processes the request and transforms JSON body keys if applicable.

Intercepts JSON requests, parses the body, transforms all keys to snake_case using the KeyTransformer helper, and replaces the request body with the transformed JSON. Non-JSON requests pass through unchanged.

Examples:

JSON transformation

# Original request body: { "firstName": "John", "lastName": "Doe" }
# Transformed body: { "first_name": "John", "last_name": "Doe" }

Non-JSON requests

# Form data, XML, and other content types pass through unchanged

Malformed JSON handling

# Invalid JSON is left unchanged and passed to the application
# The application can handle the JSON parsing error appropriately

Parameters:

  • env (Hash)

    The Rack environment hash

Returns:

  • (Array)

    The Rack response array [status, headers, body]



64
65
66
67
68
69
70
# File 'lib/securial/middleware/transform_request_keys.rb', line 64

def call(env)
  if json_request?(env)
    transform_json_body(env)
  end

  @app.call(env)
end

#json_request?(env) ⇒ Boolean (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if the request contains JSON content.

Parameters:

  • env (Hash)

    The Rack environment hash

Returns:

  • (Boolean)

    true if the request has JSON content type



80
81
82
# File 'lib/securial/middleware/transform_request_keys.rb', line 80

def json_request?(env)
  env["CONTENT_TYPE"]&.include?("application/json")
end

#read_request_body(req) ⇒ String (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reads and rewinds the request body.

Parameters:

  • req (Rack::Request)

    The Rack request object

Returns:

  • (String)

    The raw request body content



126
127
128
129
130
# File 'lib/securial/middleware/transform_request_keys.rb', line 126

def read_request_body(req)
  raw = req.body.read
  req.body.rewind
  raw
end

#replace_request_body(env, transformed_data) ⇒ void (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Replaces the request body with transformed JSON.

Parameters:

  • env (Hash)

    The Rack environment hash

  • transformed_data (Object)

    The transformed JSON data



151
152
153
154
155
# File 'lib/securial/middleware/transform_request_keys.rb', line 151

def replace_request_body(env, transformed_data)
  new_body = JSON.dump(transformed_data)
  env["rack.input"] = StringIO.new(new_body)
  env["rack.input"].rewind
end

#request_has_body?(req) ⇒ Boolean (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if the request has a body to process.

Parameters:

  • req (Rack::Request)

    The Rack request object

Returns:

  • (Boolean)

    true if the request has a non-empty body



116
117
118
# File 'lib/securial/middleware/transform_request_keys.rb', line 116

def request_has_body?(req)
  (req.body&.size || 0) > 0
end

#transform_json_body(env) ⇒ void (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Transforms JSON request body keys to snake_case.

Reads the request body, parses it as JSON, transforms all keys to snake_case, and replaces the original body with the transformed JSON. Gracefully handles empty bodies and malformed JSON.

Parameters:

  • env (Hash)

    The Rack environment hash



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/securial/middleware/transform_request_keys.rb', line 94

def transform_json_body(env)
  req = Rack::Request.new(env)

  return unless request_has_body?(req)

  raw_body = read_request_body(req)

  begin
    parsed_json = JSON.parse(raw_body)
    transformed_json = transform_keys_to_snake_case(parsed_json)
    replace_request_body(env, transformed_json)
  rescue JSON::ParserError
    # Malformed JSON - leave unchanged for application to handle
  end
end

#transform_keys_to_snake_case(json_data) ⇒ Object (private)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Transforms all keys in the JSON structure to snake_case.

Parameters:

  • json_data (Object)

    The parsed JSON data structure

Returns:

  • (Object)

    The data structure with transformed keys



138
139
140
141
142
# File 'lib/securial/middleware/transform_request_keys.rb', line 138

def transform_keys_to_snake_case(json_data)
  Securial::Helpers::KeyTransformer.deep_transform_keys(json_data) do |key|
    Securial::Helpers::KeyTransformer.underscore(key)
  end
end