glimr/response/response
HTTP Response Helpers
Wisp’s response API is low-level — building a JSON response means serializing, setting headers, and wrapping in a response struct manually. Controllers that repeat this for every endpoint accumulate boilerplate that obscures what the handler is actually trying to return. These helpers reduce each response type to a one-liner so controllers stay focused on the data, not the encoding.
Types
Deprecated: use glimr/http/response.ResponseFormat instead
The error handler middleware needs to know whether to render
an HTML error page or a JSON {"error": "..."}, and
checking Accept headers at every call site would be tedious
and error-prone. Storing the format as a typed enum on the
request context lets downstream code branch cleanly with a
single pattern match.
pub type ResponseFormat {
HTML
JSON
}
Constructors
-
HTML -
JSON
Values
pub fn empty(status: Int) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.empty instead
Some responses don’t need a body — a 204 after a successful DELETE, a 401 rejection, a 301 redirect where only headers matter. Forcing controllers to build an html or json response in those cases just adds noise.
Example:
response.empty(401)
pub fn error(status: Int) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.error instead
Apps should be able to brand their error pages without modifying framework code. Checking the app’s views/errors/ directory first lets developers drop in a custom 404.html or 500.html that takes priority, while the framework’s built-in generic page serves as a sensible default until custom ones are created.
Example:
// Returns 404 response with custom or default error page
response.error(404)
// Returns 500 response with custom or default error page
response.error(500)
pub fn header(
response: response.Response(wisp.Body),
key: String,
value: String,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.header instead
Lets controllers chain headers with the pipe operator without importing wisp. This matters because once you import wisp in a controller for headers, it’s tempting to use wisp’s response functions directly too — and then the abstraction boundary this module provides falls apart.
Example:
response.html("\"This is actually json\"", 200)
|> response.header("content-type", "application/json")
pub fn html(
content: String,
status: Int,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.html instead
Controllers shouldn’t need to import wisp just to return some HTML. Keeping all response constructors in this module means the underlying HTTP library is only referenced here — if we ever swap wisp for something else, controllers don’t change at all.
Example:
let html = "<h1>Hello World</h1>"
response.html(html, 200)
pub fn html_file(
file_path: String,
status: Int,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.html_file instead
Loading HTML from a file keeps large page content out of Gleam source code, which is cleaner for big pages and lets designers edit templates without touching application logic. The assert panics on missing files immediately rather than serving an empty response — a typo in a template path shows up the first time you hit the route, not as a silent blank page in production.
Example:
response.html_file("contact/success.html", 200)
pub fn internal_server_error() -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.internal_server_error instead
When something genuinely breaks — a database write fails, an external service is down — controllers need a clean way to bail out. Like the other status helpers, this keeps wisp imports out of controller code so the abstraction boundary holds.
pub fn json(
json: json.Json,
status: Int,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.json instead
Serializing and setting the content-type in one call prevents the common mistake of returning JSON with an HTML content type — which causes browsers and API clients to misparse the response body.
Example:
json.string("This is a json response!")
|> response.json(200)
json.object([
#("name", json.string("John Doe")),
#("email", json.string("johndoe@email.com")),
#("age", json.int(30)),
])
|> response.json(200)
pub fn loom(
content: string_tree.StringTree,
status: Int,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.string_tree instead
Loom templates return StringTree for efficient rendering. This passes the tree directly to the response body without flattening into a String first, avoiding O(n²) memory usage for large pages.
Example:
response.loom(welcome.render(), 200)
pub fn method_not_allowed(
allowed: List(http.Method),
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.method_not_allowed instead
When a URL matches but the HTTP method doesn’t — say a POST to a GET-only route — the spec requires a 405 with an Allow header listing what methods actually work. The route compiler generates these automatically so developers get correct HTTP semantics without thinking about it.
pub fn not_found() -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.not_found instead
The route compiler’s generated dispatch code needs a 404 to return when no route matches, and controllers need one when a resource lookup comes up empty. Having it here keeps wisp out of both — and if we ever want 404s to go through the custom error page system, there’s one place to change.
pub fn status_reason(status: Int) -> String
Deprecated: use glimr/http/response.status_reason instead
Showing users “404” alone means nothing to most people, but “Not Found” immediately tells them what happened. The error handler middleware uses this for JSON error messages, and the generic error page uses it for HTML — keeping the lookup here means both formats always agree on what to call each status code.
pub fn string_tree(
content: string_tree.StringTree,
status: Int,
) -> response.Response(wisp.Body)
Deprecated: use glimr/http/response.string_tree instead
You may need to return StringTree for efficient rendering. This passes the tree directly to the response body without flattening into a String first, avoiding O(n²) memory usage for large pages.
Example:
response.string_tree(welcome.render(), 200)
pub const views_path: String
Deprecated: use glimr/http/response.views_path instead
Every function that reads a view file — html_file, error, and anything else that loads templates — needs to agree on where views live. Putting the path here means changing the directory structure is a one-line fix instead of a find-and-replace across the codebase.