Converts Stripe's form-encoded nested parameters into proper nested maps.
Stripe's API uses bracket notation for nested parameters in form-encoded requests. This plug transforms them into nested Elixir maps.
Examples
# Single-level nesting
card[number]=4242424242424242
=> %{card: %{number: "4242424242424242"}}
# Multi-level nesting
payment_method_data[billing_details][name]=John Doe
=> %{payment_method_data: %{billing_details: %{name: "John Doe"}}}
# Arrays
expand[]=customer
expand[]=subscription
=> %{expand: ["customer", "subscription"]}
# Metadata
metadata[user_id]=123
metadata[session_id]=abc
=> %{metadata: %{user_id: "123", session_id: "abc"}}Usage
# In router
plug PaperTiger.Plugs.UnflattenParams
Summary
Functions
Converts maps with numeric string keys to lists.
Parses a key like "card[number]" into ["card", "number"].
Puts a value into a nested map structure with depth tracking for DoS protection.
Transforms flat params with bracket notation into nested maps.
Functions
Converts maps with numeric string keys to lists.
DoS Protection
Validates that array indices are within reasonable bounds (max: 1000) to prevent memory exhaustion from sparse arrays like items[999999].
Examples
convert_indexed_maps_to_lists(%{"0" => "a", "1" => "b"})
=> ["a", "b"]
convert_indexed_maps_to_lists(%{items: %{"0" => %{price: "p1"}, "1" => %{price: "p2"}}})
=> %{items: [%{price: "p1"}, %{price: "p2"}]}
Parses a key like "card[number]" into ["card", "number"].
Puts a value into a nested map structure with depth tracking for DoS protection.
Examples
put_nested(%{}, ["card", "number"], "4242", 0)
=> %{card: %{number: "4242"}}
put_nested(%{}, ["expand", ""], "customer", 0)
=> %{expand: ["customer"]}
Transforms flat params with bracket notation into nested maps.
DoS Protection
Enforces limits to prevent denial-of-service attacks:
- Maximum nesting depth: 10
- Maximum array index: 1000
- Maximum parameters: 1000