Current section

Files

Jump to
dream src dream@servers@mist@response.erl
Raw

src/dream@servers@mist@response.erl

-module(dream@servers@mist@response).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/dream/servers/mist/response.gleam").
-export([convert/1]).
-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(
" Response conversion from Dream to Mist format\n"
"\n"
" This module provides functions to convert Dream HTTP responses\n"
" to Mist response format, including status code, header, and cookie conversion.\n"
"\n"
" This is an internal module used by the Dream server implementation.\n"
" Most applications won't need to use this directly.\n"
).
-file("src/dream/servers/mist/response.gleam", 90).
-spec convert_header_to_tuple(dream@http@header:header()) -> {binary(),
binary()}.
convert_header_to_tuple(Header) ->
{string:lowercase(dream@http@header:header_name(Header)),
dream@http@header:header_value(Header)}.
-file("src/dream/servers/mist/response.gleam", 102).
-spec add_header(
gleam@http@response:response(mist:response_data()),
{binary(), binary()}
) -> gleam@http@response:response(mist:response_data()).
add_header(Acc, Header) ->
gleam@http@response:set_header(
Acc,
erlang:element(1, Header),
erlang:element(2, Header)
).
-file("src/dream/servers/mist/response.gleam", 109).
-spec set_all_headers(
list({binary(), binary()}),
gleam@http@response:response(mist:response_data())
) -> gleam@http@response:response(mist:response_data()).
set_all_headers(Headers, Resp) ->
gleam@list:fold(Headers, Resp, fun add_header/2).
-file("src/dream/servers/mist/response.gleam", 117).
?DOC(" Format a cookie for the Set-Cookie header\n").
-spec format_cookie_header(dream@http@cookie:cookie()) -> binary().
format_cookie_header(Cookie) ->
{cookie,
Name,
Value,
Expires,
Max_age,
Domain,
Path,
Secure,
Http_only,
Same_site} = Cookie,
Base = <<<<Name/binary, "="/utf8>>/binary, Value/binary>>,
With_expires = case Expires of
{some, Exp} ->
<<<<Base/binary, "; Expires="/utf8>>/binary,
(erlang:integer_to_binary(Exp))/binary>>;
none ->
Base
end,
With_max_age = case Max_age of
{some, Age} ->
<<<<With_expires/binary, "; Max-Age="/utf8>>/binary,
(erlang:integer_to_binary(Age))/binary>>;
none ->
With_expires
end,
With_domain = case Domain of
{some, Dom} ->
<<<<With_max_age/binary, "; Domain="/utf8>>/binary, Dom/binary>>;
none ->
With_max_age
end,
With_path = case Path of
{some, P} ->
<<<<With_domain/binary, "; Path="/utf8>>/binary, P/binary>>;
none ->
With_domain
end,
With_secure = case Secure of
true ->
<<With_path/binary, "; Secure"/utf8>>;
false ->
With_path
end,
With_http_only = case Http_only of
true ->
<<With_secure/binary, "; HttpOnly"/utf8>>;
false ->
With_secure
end,
case Same_site of
{some, strict} ->
<<With_http_only/binary, "; SameSite=Strict"/utf8>>;
{some, lax} ->
<<With_http_only/binary, "; SameSite=Lax"/utf8>>;
{some, none} ->
<<With_http_only/binary, "; SameSite=None"/utf8>>;
none ->
With_http_only
end.
-file("src/dream/servers/mist/response.gleam", 94).
-spec add_cookie_header(list({binary(), binary()}), dream@http@cookie:cookie()) -> list({binary(),
binary()}).
add_cookie_header(Acc, Cookie) ->
Cookie_header = format_cookie_header(Cookie),
[{<<"set-cookie"/utf8>>, Cookie_header} | Acc].
-file("src/dream/servers/mist/response.gleam", 52).
?DOC(
" Convert Dream response to Mist response format\n"
"\n"
" Converts a Dream HTTP response to Mist's response format.\n"
" This includes converting:\n"
"\n"
" - Status code (Int remains Int)\n"
" - Headers (Dream Header to Mist tuple format)\n"
" - Cookies (formatted as Set-Cookie headers)\n"
" - Body (Text/Bytes/Stream to Mist ResponseData)\n"
"\n"
" The conversion handles all three body types:\n"
" - `Text`: Converted to bytes and sent immediately\n"
" - `Bytes`: Sent as-is\n"
" - `Stream`: Converted to chunked transfer encoding\n"
"\n"
" ## Parameters\n"
"\n"
" - `dream_resp`: Dream Response with all fields populated\n"
"\n"
" ## Returns\n"
"\n"
" Mist HTTP response ready to send to the client\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" // Internal use - normally called by the request handler\n"
" let dream_resp = response.json_response(200, user_json)\n"
" let mist_resp = convert(dream_resp)\n"
" // Mist server sends mist_resp to client\n"
" ```\n"
).
-spec convert(dream@http@response:response()) -> gleam@http@response:response(mist:response_data()).
convert(Dream_resp) ->
Status_code = erlang:element(2, Dream_resp),
Headers = gleam@list:map(
erlang:element(4, Dream_resp),
fun convert_header_to_tuple/1
),
Headers_with_cookies = gleam@list:fold(
erlang:element(5, Dream_resp),
Headers,
fun add_cookie_header/2
),
Headers_with_content_type = case erlang:element(6, Dream_resp) of
{some, Ct} ->
gleam@list:key_set(
Headers_with_cookies,
<<"content-type"/utf8>>,
Ct
);
none ->
Headers_with_cookies
end,
Response_data = case erlang:element(3, Dream_resp) of
{text, Text} ->
{bytes, gleam_stdlib:wrap_list(Text)};
{bytes, Bytes} ->
{bytes, gleam@bytes_tree:from_bit_array(Bytes)};
{stream, Stream} ->
Byte_stream = begin
_pipe = Stream,
gleam@yielder:map(_pipe, fun gleam@bytes_tree:from_bit_array/1)
end,
{chunked, Byte_stream}
end,
Resp_with_body = begin
_pipe@1 = gleam@http@response:new(Status_code),
gleam@http@response:set_body(_pipe@1, Response_data)
end,
set_all_headers(Headers_with_content_type, Resp_with_body).