What do people think of this for modelling HTTP Status Codes?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Http.Status : [
Success [Ok, Created, NoContent, Other U16],
Redirect [MovedPermanently, Found, NotModified, Other U16],
ClientErr [BadRequest, Unauthorized, Forbidden, NotFound, TooManyRequests, Other U16],
ServerErr [InternalServerError, BadGateway, ServiceUnavailable, GatewayTimeout, Other U16],
]
Instead of giving a raw U16 and asking users to pattern match on that, we can provide more type safety.
I've never been a fan of that personally
I'm always like "I want to match on 401...which constant is that again? Unauthorized or Forbidden?"
etc.
Interesting... this is what I was thinking https://gist.github.com/lukewilliamboswell/0ad4474080714357e6b4200af397c0b0
I could add the number into the name, Ok200, BadRequest400, ...
Or add a helper as_u16: Status -> U16
Also can just leave it as raw U16... but then it's up the the app author to choose the correct numbers. Which is also Ok
I'm curious what others think, might just be my bias from having so many of the codes in muscle memory :sweat_smile:
I do think ClientErr BadRequest is clearer than 400 though when reading
could you not just make functions is_success is_redirect is_client_err is_server_err ? (nvm i forgot bools are bad)
or a function Http.status_type which does Status -> [Success, Redirect, ClientErr, ServerErr]
I've been trying to think about how it will be used in downstream code. This is an example of making a request using basic-cli.
# Basic HTTP GET request
main! = \{} ->
response = Http.send! {
method: Get,
headers: [],
url: "http://www.example.com",
body: [],
timeout: TimeoutMilliseconds 5000,
}
when response.status is
Info _ -> Stdout.line! "Informational - Request received, continuing process."
Success _ -> Stdout.line! "Success - The action was successfully received, understood, and accepted"
Redirect _ -> Stdout.line! "Redirection - Further action must be taken in order to complete the request"
ClientErr _ -> Stdout.line! "Client Error - The request contains bad syntax or cannot be fulfilled"
ServerErr _ -> Stdout.line! "Server Error - The server failed to fulfill an apparently valid request"
My goal is to use the tags to be descriptive, and avoid function calls.
I'm missing Info... 1xx series... I'll add that too
edit: or maybe we don't need these... they look like intermediate status codes
I also feel that I know the http numbers better than the status code names.
Seperately, I don't think I've ever ran into a situation where I wanted to exhaustively check all individual status codes of an http response, but maybe folks have different experiences. If users will not rely on exhaustiveness checking, then I don't think there's many benefits to expressing status codes as tags in terms of type-safety.
The one thing I have done is to check for ranges of status code responses, but for that use case ints are more flexible because you can easily differentiate between >= 400 to match all errors and >= 500 to match server errors, for instance.
Thank you @Jasper Woudenberg
I'm going to revert my changes in this PR https://github.com/roc-lang/basic-cli/blob/refactor/platform/InternalHttp.roc from this back to a U16.
I still think it's nice to model it like this, but I'd like to land these upgrades, and we don't need to solve this problem right now. it's easier to be conservative for now and leave it as it currently is. People can always model it in userland if they want type safety.
I think a U16 makes sense for the API, but a module for StatusCodes that exposes the status codes as constants is very useful
I definitely prefer a number
From my experience the names can be more useful, but it depends on the environment. It just helps to reason with others that might need to read or understand the code rarely (UX and the like). Given a proper logging solution you should anyways have the http status code logged as well. Where I'd agree is that when looking for the error it might happen that more people are looking for what's actually visible in the browser. So somehow the code should be included.
Last updated: Jun 16 2026 at 16:19 UTC