-module(dream@http@response). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/dream/http/response.gleam"). -export([text_response/2, json_response/2, html_response/2, redirect_response/2, empty_response/1, binary_response/3, stream_response/3, sse_response/3]). -export_type([response_body/0, response/0]). -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( " HTTP response types and builders\n" "\n" " Core response types and convenient functions for building common HTTP responses.\n" " This module provides builders for text, JSON, HTML, binary, and streaming responses.\n" "\n" " ## Quick Examples\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" "\n" " // Text response\n" " response.text_response(status.ok, \"Hello, World!\")\n" "\n" " // JSON response\n" " response.json_response(status.ok, json.to_string(user_json))\n" "\n" " // HTML response\n" " response.html_response(status.ok, \"

Welcome

\")\n" "\n" " // Redirect\n" " response.redirect_response(status.see_other, \"/login\")\n" " ```\n" ). -type response_body() :: {text, binary()} | {bytes, bitstring()} | {stream, gleam@yielder:yielder(bitstring())}. -type response() :: {response, integer(), response_body(), list(dream@http@header:header()), list(dream@http@cookie:cookie()), gleam@option:option(binary())}. -file("src/dream/http/response.gleam", 116). ?DOC( " Create a plain text response\n" "\n" " Returns a response with `text/plain` content type.\n" " Use for plain text output that isn't JSON, HTML, or another format.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response.{text_response}\n" " import dream/http/status.{ok}\n" "\n" " pub fn healthcheck(request, context, services) {\n" " text_response(ok, \"OK\")\n" " }\n" " ```\n" ). -spec text_response(integer(), binary()) -> response(). text_response(Status, Body) -> {response, Status, {text, Body}, [{header, <<"Content-Type"/utf8>>, <<"text/plain; charset=utf-8"/utf8>>}], [], {some, <<"text/plain; charset=utf-8"/utf8>>}}. -file("src/dream/http/response.gleam", 148). ?DOC( " Create a JSON response\n" "\n" " Returns a response with `application/json` content type.\n" " Pass a JSON string (from `gleam/json` or similar). This function\n" " doesn't encode JSON for you—use `gleam/json` to encode first.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response.{json_response}\n" " import dream/http/status.{ok}\n" " import gleam/json\n" "\n" " pub fn show_user(request, context, services) {\n" " let user_json = json.object([\n" " #(\"id\", json.int(123)),\n" " #(\"name\", json.string(\"Alice\")),\n" " ])\n" " \n" " json_response(ok, json.to_string(user_json))\n" " }\n" " ```\n" ). -spec json_response(integer(), binary()) -> response(). json_response(Status, Body) -> {response, Status, {text, Body}, [{header, <<"Content-Type"/utf8>>, <<"application/json; charset=utf-8"/utf8>>}], [], {some, <<"application/json; charset=utf-8"/utf8>>}}. -file("src/dream/http/response.gleam", 180). ?DOC( " Create an HTML response\n" "\n" " Returns a response with `text/html` content type.\n" " Use for HTML pages, HTMX responses, or HTML fragments.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" "\n" " pub fn index(request, context, services) {\n" " let html = \"\n" " \n" " \n" "

Welcome

\n" " \n" " \"\n" " \n" " response.html_response(status.ok, html)\n" " }\n" " ```\n" ). -spec html_response(integer(), binary()) -> response(). html_response(Status, Body) -> {response, Status, {text, Body}, [{header, <<"Content-Type"/utf8>>, <<"text/html; charset=utf-8"/utf8>>}], [], {some, <<"text/html; charset=utf-8"/utf8>>}}. -file("src/dream/http/response.gleam", 215). ?DOC( " Create a redirect response\n" "\n" " Returns a redirect with the Location header set. Use with redirect\n" " status codes (301, 302, 303, 307) to send the client to a new URL.\n" "\n" " Common patterns:\n" " - `303 See Other`: After POST/PUT/DELETE, redirect to GET (prevents duplicate submission)\n" " - `302 Found`: Temporary redirect (can change method)\n" " - `301 Moved Permanently`: Permanent redirect (update bookmarks/search engines)\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" "\n" " pub fn create_post(request, context, services) {\n" " // After creating post, redirect to view it\n" " let post_id = 123\n" " response.redirect_response(\n" " status.see_other,\n" " \"/posts/\" <> int.to_string(post_id)\n" " )\n" " }\n" " ```\n" ). -spec redirect_response(integer(), binary()) -> response(). redirect_response(Status, Location) -> {response, Status, {text, <<""/utf8>>}, [{header, <<"Location"/utf8>>, Location}], [], none}. -file("src/dream/http/response.gleam", 243). ?DOC( " Create an empty response with no body\n" "\n" " Returns a response with no content. Commonly used with:\n" " - `204 No Content`: Successful request with no data to return\n" " - `404 Not Found`: Resource doesn't exist\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" "\n" " pub fn delete_user(request, context, services) {\n" " // After successful deletion, return 204 with no body\n" " delete_from_db(services.db, user_id)\n" " response.empty_response(status.no_content)\n" " }\n" " ```\n" ). -spec empty_response(integer()) -> response(). empty_response(Status) -> {response, Status, {text, <<""/utf8>>}, [], [], none}. -file("src/dream/http/response.gleam", 274). ?DOC( " Create a binary response for files, images, PDFs, etc.\n" "\n" " Returns a response with binary data. Use for images, PDFs, zip files,\n" " or any non-text content. You must specify the content type.\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" " import simplifile\n" "\n" " pub fn serve_image(request, context, services) {\n" " case simplifile.read_bits(\"logo.png\") {\n" " Ok(image_data) ->\n" " response.binary_response(status.ok, image_data, \"image/png\")\n" " Error(_) ->\n" " response.empty_response(status.not_found)\n" " }\n" " }\n" " ```\n" ). -spec binary_response(integer(), bitstring(), binary()) -> response(). binary_response(Status, Body, Content_type) -> {response, Status, {bytes, Body}, [{header, <<"Content-Type"/utf8>>, Content_type}], [], {some, Content_type}}. -file("src/dream/http/response.gleam", 312). ?DOC( " Create a streaming response for large files or real-time data\n" "\n" " Returns a response with a stream of chunks. Use for:\n" " - Large files (stream without loading entire file in memory)\n" " - Real-time data (AI responses, logs, events)\n" " - CSV exports (generate rows on-demand)\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" " import gleam/yielder\n" "\n" " pub fn export_users(request, context, services) {\n" " let user_stream = \n" " query_all_users(services.db)\n" " |> yielder.from_list\n" " |> yielder.map(user_to_csv_row)\n" " |> yielder.map(fn(row) { <> })\n" " \n" " response.stream_response(status.ok, user_stream, \"text/csv\")\n" " }\n" " ```\n" ). -spec stream_response(integer(), gleam@yielder:yielder(bitstring()), binary()) -> response(). stream_response(Status, Stream, Content_type) -> {response, Status, {stream, Stream}, [{header, <<"Content-Type"/utf8>>, Content_type}], [], {some, Content_type}}. -file("src/dream/http/response.gleam", 355). ?DOC( " Create a Server-Sent Events (SSE) response\n" "\n" " Returns a streaming response configured for Server-Sent Events.\n" " SSE enables server-to-client real-time updates over HTTP.\n" "\n" " The response includes:\n" " - `Content-Type: text/event-stream`\n" " - `Cache-Control: no-cache`\n" " - `Connection: keep-alive`\n" "\n" " ## Example\n" "\n" " ```gleam\n" " import dream/http/response\n" " import dream/http/status\n" " import gleam/yielder\n" "\n" " pub fn events(request, context, services) {\n" " let event_stream = \n" " subscribe_to_events(services)\n" " |> yielder.map(format_sse_event)\n" " \n" " response.sse_response(status.ok, event_stream, \"text/event-stream\")\n" " }\n" "\n" " fn format_sse_event(data: String) -> BitArray {\n" " <<\"data: \", data:utf8, \"\\n\\n\":utf8>>\n" " }\n" " ```\n" ). -spec sse_response(integer(), gleam@yielder:yielder(bitstring()), binary()) -> response(). sse_response(Status, Stream, Content_type) -> {response, Status, {stream, Stream}, [{header, <<"Content-Type"/utf8>>, Content_type}, {header, <<"Cache-Control"/utf8>>, <<"no-cache"/utf8>>}, {header, <<"Connection"/utf8>>, <<"keep-alive"/utf8>>}], [], {some, Content_type}}.