Current section

Files

Jump to
nex_core lib nex req.ex
Raw

lib/nex/req.ex

defmodule Nex.Req do
@moduledoc """
Standardized Request object for API handlers.
Fully mimics Next.js API Routes behavior with minimal additions.
## Next.js Standard Fields
* `query` - Path params + query string params (Next.js `req.query`)
* `body` - Request body params (Next.js `req.body`)
* `headers` - Request headers as a Map
* `cookies` - Request cookies as a Map
* `method` - HTTP method (uppercase string)
## Parameter Merging Behavior
Like Next.js, `req.query` contains both dynamic path parameters and query string parameters.
When the same key appears in both, **path parameters take precedence**.
For example, `GET /api/users/123?id=456`:
- `req.query["id"]``"123"` (path parameter wins)
`req.body` is completely independent and never merged with `req.query`.
## Examples
# GET /api/users/[id]?page=2
def get(req) do
user_id = req.query["id"] # From path parameter [id]
page = req.query["page"] # From query string
Nex.json(%{user_id: user_id, page: page})
end
# POST /api/users
def post(req) do
name = req.body["name"]
email = req.body["email"]
Nex.json(%{message: "User created"}, status: 201)
end
## Comparison with Next.js
| Next.js | Nex | Notes |
|---------|-----|-------|
| `req.query` | `req.query` | Identical behavior |
| `req.body` | `req.body` | Identical behavior |
| `req.headers` | `req.headers` | Identical behavior |
| `req.cookies` | `req.cookies` | Identical behavior |
| `req.method` | `req.method` | Identical behavior |
"""
defstruct [
# Next.js standard fields
:query, # Path params + query string (Next.js req.query)
:body, # Request body (Next.js req.body)
:headers, # Request headers (Map)
:cookies, # Request cookies (Map)
:method, # HTTP method (String, uppercase)
# Framework internals
:path, # Request path (String)
:private # Framework internal data (Map)
]
@doc """
Constructs a Nex.Req from a Plug.Conn.
This function normalizes the Plug.Conn into a Next.js-compatible request object.
"""
def from_plug_conn(%Plug.Conn{} = conn, path_params \\ %{}) do
conn = conn
|> Plug.Conn.fetch_query_params()
|> Plug.Conn.fetch_cookies()
# Normalize body_params: ensure it's always a Map (never Unfetched)
body_params = case conn.body_params do
%Plug.Conn.Unfetched{} -> %{}
params when is_map(params) -> params
_ -> %{}
end
# Convert headers list to Map
headers = Map.new(conn.req_headers)
# Next.js style: path params override query params
query = Map.merge(conn.query_params, path_params)
%__MODULE__{
# Next.js standard - exactly the same behavior
query: query,
body: body_params,
headers: headers,
cookies: conn.cookies,
method: conn.method,
# Framework internals
path: conn.request_path,
private: conn.private
}
end
end