Current section
Files
Jump to
Current section
Files
src/dream@dream.erl
-module(dream@dream).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/dream/dream.gleam").
-export([execute_route/5, route_request/4, parse_cookie_string/1, parse_cookies_from_headers/1]).
-export_type([dream/3]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Core Dream server type and shared functionality\n"
"\n"
" This module provides the generic Dream server type and core routing\n"
" functionality that is shared across all server implementations.\n"
"\n"
" Most applications will use `dream/servers/mist/server` instead of this\n"
" module directly. This module contains the core types and routing logic\n"
" that the server implementations build upon.\n"
).
-type dream(ADMI, ADMJ, ADMK) :: {dream,
ADMI,
gleam@option:option(dream@router:router(ADMJ, ADMK)),
ADMJ,
gleam@option:option(ADMK),
integer()}.
-file("src/dream/dream.gleam", 158).
?DOC(
" Execute a route with its params, middleware, and controller\n"
"\n"
" Helper function to execute a route that's already been matched.\n"
" Used by route_request and can be called directly when route is already known\n"
" (e.g., in server handlers that need to find the route first to determine\n"
" if it's streaming).\n"
"\n"
" ## Parameters\n"
"\n"
" - `route`: The matched route to execute\n"
" - `request`: HTTP request (may have body/stream already attached)\n"
" - `params`: Path parameters extracted from the route pattern\n"
" - `context`: Application context\n"
" - `services`: Application services\n"
"\n"
" ## Returns\n"
"\n"
" HTTP response from the controller\n"
).
-spec execute_route(
dream@router:route(ADMP, ADMQ),
dream@http@request:request(),
list({binary(), binary()}),
ADMP,
ADMQ
) -> dream@http@response:response().
execute_route(Route, Request, Params, Context, Services) ->
Request_with_params = dream@http@request:set_params(Request, Params),
Controller_chain = dream@router:build_controller_chain(
erlang:element(5, Route),
erlang:element(4, Route)
),
Controller_chain(Request_with_params, Context, Services).
-file("src/dream/dream.gleam", 118).
?DOC(
" Route a request through the router\n"
"\n"
" Takes an incoming HTTP request, matches it against the router's routes,\n"
" executes any middleware, calls the appropriate controller, and returns\n"
" the response.\n"
"\n"
" This is the core routing function that:\n"
" 1. Finds a matching route based on method and path\n"
" 2. Extracts path parameters (e.g., `:id` from `/users/:id`)\n"
" 3. Builds the middleware chain\n"
" 4. Executes middleware and controller\n"
" 5. Returns the response\n"
"\n"
" If no route matches, returns a 404 response.\n"
"\n"
" ## Parameters\n"
"\n"
" - `router_instance`: Router with all routes configured\n"
" - `request`: HTTP request to route\n"
" - `context`: Request-specific context\n"
" - `services`: Application services (database, cache, etc.)\n"
"\n"
" ## Returns\n"
"\n"
" HTTP response from the controller or 404 if no route matches\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" // Internal use - normally called by the request handler\n"
" let response = route_request(\n"
" my_router,\n"
" incoming_request,\n"
" request_context,\n"
" my_services\n"
" )\n"
" ```\n"
).
-spec route_request(
dream@router:router(ADML, ADMM),
dream@http@request:request(),
ADML,
ADMM
) -> dream@http@response:response().
route_request(Router_instance, Request, Context, Services) ->
case dream@router:find_route(Router_instance, Request) of
{some, {Route, Params}} ->
execute_route(Route, Request, Params, Context, Services);
none ->
{response,
404,
{text, <<"Route not found"/utf8>>},
[{header,
<<"Content-Type"/utf8>>,
<<"text/plain; charset=utf-8"/utf8>>}],
[],
{some, <<"text/plain; charset=utf-8"/utf8>>}}
end.
-file("src/dream/dream.gleam", 217).
-spec is_cookie_header(dream@http@header:header()) -> boolean().
is_cookie_header(Header) ->
string:lowercase(dream@http@header:header_name(Header)) =:= <<"cookie"/utf8>>.
-file("src/dream/dream.gleam", 251).
-spec parse_cookie_pair(binary()) -> dream@http@cookie:cookie().
parse_cookie_pair(Cookie_pair) ->
case gleam@string:split(Cookie_pair, <<"="/utf8>>) of
[Name, Value] ->
Name@1 = gleam@string:trim(Name),
Value@1 = gleam@string:trim(Value),
dream@http@cookie:simple_cookie(Name@1, Value@1);
_ ->
Name@2 = gleam@string:trim(Cookie_pair),
dream@http@cookie:simple_cookie(Name@2, <<""/utf8>>)
end.
-file("src/dream/dream.gleam", 245).
?DOC(
" Parse a cookie header string into a list of cookies\n"
"\n"
" Parses the raw cookie header value format (\"name1=value1; name2=value2\")\n"
" into a list of Cookie objects with simple cookies (no attributes).\n"
"\n"
" ## Parameters\n"
"\n"
" - `cookie_string`: Raw Cookie header value\n"
"\n"
" ## Returns\n"
"\n"
" List of parsed simple cookies\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" let cookie_str = \"session=abc123; theme=dark; lang=en\"\n"
" let cookies = parse_cookie_string(cookie_str)\n"
" // Returns: [\n"
" // simple_cookie(\"session\", \"abc123\"),\n"
" // simple_cookie(\"theme\", \"dark\"),\n"
" // simple_cookie(\"lang\", \"en\")\n"
" // ]\n"
" ```\n"
).
-spec parse_cookie_string(binary()) -> list(dream@http@cookie:cookie()).
parse_cookie_string(Cookie_string) ->
_pipe = Cookie_string,
_pipe@1 = gleam@string:split(_pipe, <<";"/utf8>>),
gleam@list:map(_pipe@1, fun parse_cookie_pair/1).
-file("src/dream/dream.gleam", 205).
?DOC(
" Parse cookies from HTTP headers\n"
"\n"
" Extracts cookies from the Cookie header in a list of headers.\n"
" Parses the cookie string format (\"name1=value1; name2=value2\") into\n"
" a list of Cookie objects.\n"
"\n"
" ## Parameters\n"
"\n"
" - `headers`: List of HTTP headers to search\n"
"\n"
" ## Returns\n"
"\n"
" List of parsed cookies (empty list if no Cookie header found)\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream/http/header.{Header}\n"
"\n"
" let headers = [\n"
" Header(\"Content-Type\", \"application/json\"),\n"
" Header(\"Cookie\", \"session=abc123; theme=dark\"),\n"
" ]\n"
"\n"
" let cookies = parse_cookies_from_headers(headers)\n"
" // Returns: [\n"
" // Cookie(name: \"session\", value: \"abc123\", ...),\n"
" // Cookie(name: \"theme\", value: \"dark\", ...)\n"
" // ]\n"
" ```\n"
).
-spec parse_cookies_from_headers(list(dream@http@header:header())) -> list(dream@http@cookie:cookie()).
parse_cookies_from_headers(Headers) ->
Cookie_header = gleam@list:find(Headers, fun is_cookie_header/1),
case Cookie_header of
{ok, Header} ->
Cookie_string = dream@http@header:header_value(Header),
parse_cookie_string(Cookie_string);
{error, _} ->
[]
end.