aboutsummaryrefslogtreecommitdiff
path: root/aoc2023/build/packages/gleam_http/src
diff options
context:
space:
mode:
Diffstat (limited to 'aoc2023/build/packages/gleam_http/src')
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http.gleam560
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam128
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam267
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam141
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam82
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http.erl626
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl153
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@request.erl202
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@response.erl97
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam@http@service.erl82
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http.app.src12
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http_native.erl88
-rw-r--r--aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs38
13 files changed, 0 insertions, 2476 deletions
diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http.gleam
deleted file mode 100644
index a892006..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam/http.gleam
+++ /dev/null
@@ -1,560 +0,0 @@
-//// Functions for working with HTTP data structures in Gleam.
-////
-//// This module makes it easy to create and modify Requests and Responses, data types.
-//// A general HTTP message type is defined that enables functions to work on both requests and responses.
-////
-//// This module does not implement a HTTP client or HTTP server, but it can be used as a base for them.
-
-import gleam/dynamic.{type DecodeError, type Dynamic, DecodeError}
-import gleam/string
-import gleam/bit_array
-import gleam/result
-import gleam/list
-import gleam/bool
-
-/// HTTP standard method as defined by [RFC 2616](https://tools.ietf.org/html/rfc2616),
-/// and PATCH which is defined by [RFC 5789](https://tools.ietf.org/html/rfc5789).
-pub type Method {
- Get
- Post
- Head
- Put
- Delete
- Trace
- Connect
- Options
- Patch
-
- /// Non-standard but valid HTTP methods.
- Other(String)
-}
-
-// TODO: check if the a is a valid HTTP method (i.e. it is a token, as per the
-// spec) and return Ok(Other(s)) if so.
-pub fn parse_method(s) -> Result(Method, Nil) {
- case string.lowercase(s) {
- "connect" -> Ok(Connect)
- "delete" -> Ok(Delete)
- "get" -> Ok(Get)
- "head" -> Ok(Head)
- "options" -> Ok(Options)
- "patch" -> Ok(Patch)
- "post" -> Ok(Post)
- "put" -> Ok(Put)
- "trace" -> Ok(Trace)
- _ -> Error(Nil)
- }
-}
-
-pub fn method_to_string(method: Method) -> String {
- case method {
- Connect -> "connect"
- Delete -> "delete"
- Get -> "get"
- Head -> "head"
- Options -> "options"
- Patch -> "patch"
- Post -> "post"
- Put -> "put"
- Trace -> "trace"
- Other(s) -> s
- }
-}
-
-/// The two URI schemes for HTTP
-///
-pub type Scheme {
- Http
- Https
-}
-
-/// Convert a scheme into a string.
-///
-/// # Examples
-///
-/// > scheme_to_string(Http)
-/// "http"
-///
-/// > scheme_to_string(Https)
-/// "https"
-///
-pub fn scheme_to_string(scheme: Scheme) -> String {
- case scheme {
- Http -> "http"
- Https -> "https"
- }
-}
-
-/// Parse a HTTP scheme from a string
-///
-/// # Examples
-///
-/// > scheme_from_string("http")
-/// Ok(Http)
-///
-/// > scheme_from_string("ftp")
-/// Error(Nil)
-///
-pub fn scheme_from_string(scheme: String) -> Result(Scheme, Nil) {
- case string.lowercase(scheme) {
- "http" -> Ok(Http)
- "https" -> Ok(Https)
- _ -> Error(Nil)
- }
-}
-
-pub fn method_from_dynamic(value: Dynamic) -> Result(Method, List(DecodeError)) {
- case do_method_from_dynamic(value) {
- Ok(method) -> Ok(method)
- Error(_) -> Error([DecodeError("HTTP method", dynamic.classify(value), [])])
- }
-}
-
-pub type MultipartHeaders {
- /// The headers for the part have been fully parsed.
- MultipartHeaders(
- headers: List(Header),
- /// The remaining content that has not yet been parsed. This will contain
- /// the body for this part, if any, and can be parsed with the
- /// `parse_multipart_body` function.
- remaining: BitArray,
- )
- /// More input is required to parse the headers for this part.
- MoreRequiredForHeaders(
- /// Call this function to continue parsing the headers for this part.
- continuation: fn(BitArray) -> Result(MultipartHeaders, Nil),
- )
-}
-
-pub type MultipartBody {
- /// The body for the part has been fully parsed.
- MultipartBody(
- // The rest of the body for this part. The full body of the part is this
- // concatenated onto the end of each chunk returned by any previous
- // `MoreRequiredForBody` returns.
- chunk: BitArray,
- /// This is `True` if this was the last part in the multipart message,
- /// otherwise there are more parts to parse.
- done: Bool,
- /// The remaining content that has not yet been parsed. This will contain
- /// the next part if `done` is `False`, otherwise it will contain the
- /// epilogue, if any.
- remaining: BitArray,
- )
- MoreRequiredForBody(
- // The body that has been parsed so far. The full body of the part is this
- // concatenated with the chunk returned by each `MoreRequiredForBody` return
- // value, and the final `MultipartBody` return value.
- chunk: BitArray,
- /// Call this function to continue parsing the body for this part.
- continuation: fn(BitArray) -> Result(MultipartBody, Nil),
- )
-}
-
-/// Parse the headers for part of a multipart message, as defined in RFC 2045.
-///
-/// This function skips any preamble before the boundary. The preamble may be
-/// retrieved using `parse_multipart_body`.
-///
-/// This function will accept input of any size, it is up to the caller to limit
-/// it if needed.
-///
-/// To enable streaming parsing of multipart messages, this function will return
-/// a continuation if there is not enough data to fully parse the headers.
-/// Further information is available in the documentation for `MultipartBody`.
-///
-pub fn parse_multipart_headers(
- data: BitArray,
- boundary: String,
-) -> Result(MultipartHeaders, Nil) {
- let boundary = bit_array.from_string(boundary)
- // TODO: rewrite this to use a bit pattern once JavaScript supports
- // the `b:binary-size(bsize)` pattern.
- let prefix = <<45, 45, boundary:bits>>
- case bit_array.slice(data, 0, bit_array.byte_size(prefix)) == Ok(prefix) {
- // There is no preamble, parse the headers.
- True -> parse_headers_after_prelude(data, boundary)
- // There is a preamble, skip it before parsing.
- False -> skip_preamble(data, boundary)
- }
-}
-
-/// Parse the body for part of a multipart message, as defined in RFC 2045. The
-/// body is everything until the next boundary. This function is generally to be
-/// called after calling `parse_multipart_headers` for a given part.
-///
-/// This function will accept input of any size, it is up to the caller to limit
-/// it if needed.
-///
-/// To enable streaming parsing of multipart messages, this function will return
-/// a continuation if there is not enough data to fully parse the body, along
-/// with the data that has been parsed so far. Further information is available
-/// in the documentation for `MultipartBody`.
-///
-pub fn parse_multipart_body(
- data: BitArray,
- boundary: String,
-) -> Result(MultipartBody, Nil) {
- boundary
- |> bit_array.from_string
- |> parse_body_with_bit_array(data, _)
-}
-
-fn parse_body_with_bit_array(
- data: BitArray,
- boundary: BitArray,
-) -> Result(MultipartBody, Nil) {
- let bsize = bit_array.byte_size(boundary)
- let prefix = bit_array.slice(data, 0, 2 + bsize)
- case prefix == Ok(<<45, 45, boundary:bits>>) {
- True -> Ok(MultipartBody(<<>>, done: False, remaining: data))
- False -> parse_body_loop(data, boundary, <<>>)
- }
-}
-
-fn parse_body_loop(
- data: BitArray,
- boundary: BitArray,
- body: BitArray,
-) -> Result(MultipartBody, Nil) {
- let dsize = bit_array.byte_size(data)
- let bsize = bit_array.byte_size(boundary)
- let required = 6 + bsize
- case data {
- _ if dsize < required -> {
- more_please_body(parse_body_loop(_, boundary, <<>>), body, data)
- }
-
- // TODO: flatten this into a single case expression once JavaScript supports
- // the `b:binary-size(bsize)` pattern.
- //
- // \r\n
- <<13, 10, data:bytes>> -> {
- let desired = <<45, 45, boundary:bits>>
- let size = bit_array.byte_size(desired)
- let dsize = bit_array.byte_size(data)
- let prefix = bit_array.slice(data, 0, size)
- let rest = bit_array.slice(data, size, dsize - size)
- case prefix == Ok(desired), rest {
- // --boundary\r\n
- True, Ok(<<13, 10, _:bytes>>) ->
- Ok(MultipartBody(body, done: False, remaining: data))
-
- // --boundary--
- True, Ok(<<45, 45, data:bytes>>) ->
- Ok(MultipartBody(body, done: True, remaining: data))
-
- False, _ -> parse_body_loop(data, boundary, <<body:bits, 13, 10>>)
- _, _ -> Error(Nil)
- }
- }
-
- <<char, data:bytes>> -> {
- parse_body_loop(data, boundary, <<body:bits, char>>)
- }
- }
-}
-
-fn parse_headers_after_prelude(
- data: BitArray,
- boundary: BitArray,
-) -> Result(MultipartHeaders, Nil) {
- let dsize = bit_array.byte_size(data)
- let bsize = bit_array.byte_size(boundary)
- let required_size = bsize + 4
-
- // TODO: this could be written as a single case expression if JavaScript had
- // support for the `b:binary-size(bsize)` pattern. Rewrite this once the
- // compiler support this.
-
- use <- bool.guard(
- when: dsize < required_size,
- return: more_please_headers(parse_headers_after_prelude(_, boundary), data),
- )
-
- use prefix <- result.try(bit_array.slice(data, 0, required_size - 2))
- use second <- result.try(bit_array.slice(data, 2 + bsize, 2))
- let desired = <<45, 45, boundary:bits>>
-
- use <- bool.guard(prefix != desired, return: Error(Nil))
-
- case second == <<45, 45>> {
- // --boundary--
- // The last boundary. Return the epilogue.
- True -> {
- let rest_size = dsize - required_size
- use data <- result.map(bit_array.slice(data, required_size, rest_size))
- MultipartHeaders([], remaining: data)
- }
-
- // --boundary
- False -> {
- let start = required_size - 2
- let rest_size = dsize - required_size + 2
- use data <- result.try(bit_array.slice(data, start, rest_size))
- do_parse_headers(data)
- }
- }
-}
-
-fn skip_preamble(
- data: BitArray,
- boundary: BitArray,
-) -> Result(MultipartHeaders, Nil) {
- let data_size = bit_array.byte_size(data)
- let boundary_size = bit_array.byte_size(boundary)
- let required = boundary_size + 4
- case data {
- _ if data_size < required ->
- more_please_headers(skip_preamble(_, boundary), data)
-
- // TODO: change this to use one non-nested case expression once the compiler
- // supports the `b:binary-size(bsize)` pattern on JS.
- // \r\n--
- <<13, 10, 45, 45, data:bytes>> -> {
- case bit_array.slice(data, 0, boundary_size) {
- // --boundary
- Ok(prefix) if prefix == boundary -> {
- let start = boundary_size
- let length = bit_array.byte_size(data) - boundary_size
- use rest <- result.try(bit_array.slice(data, start, length))
- do_parse_headers(rest)
- }
- Ok(_) -> skip_preamble(data, boundary)
- Error(_) -> Error(Nil)
- }
- }
-
- <<_, data:bytes>> -> skip_preamble(data, boundary)
- }
-}
-
-fn skip_whitespace(data: BitArray) -> BitArray {
- case data {
- // Space or tab.
- <<32, data:bytes>> | <<9, data:bytes>> -> skip_whitespace(data)
- _ -> data
- }
-}
-
-fn do_parse_headers(data: BitArray) -> Result(MultipartHeaders, Nil) {
- case data {
- // \r\n\r\n
- // We've reached the end, there are no headers.
- <<13, 10, 13, 10, data:bytes>> -> Ok(MultipartHeaders([], remaining: data))
-
- // \r\n
- // Skip the line break after the boundary.
- <<13, 10, data:bytes>> -> parse_header_name(data, [], <<>>)
-
- <<13>> | <<>> -> more_please_headers(do_parse_headers, data)
-
- _ -> Error(Nil)
- }
-}
-
-fn parse_header_name(
- data: BitArray,
- headers: List(Header),
- name: BitArray,
-) -> Result(MultipartHeaders, Nil) {
- case skip_whitespace(data) {
- // :
- <<58, data:bytes>> ->
- data
- |> skip_whitespace
- |> parse_header_value(headers, name, <<>>)
-
- <<char, data:bytes>> ->
- parse_header_name(data, headers, <<name:bits, char>>)
-
- <<>> -> more_please_headers(parse_header_name(_, headers, name), data)
- }
-}
-
-fn parse_header_value(
- data: BitArray,
- headers: List(Header),
- name: BitArray,
- value: BitArray,
-) -> Result(MultipartHeaders, Nil) {
- let size = bit_array.byte_size(data)
- case data {
- // We need at least 4 bytes to check for the end of the headers.
- _ if size < 4 ->
- fn(data) {
- data
- |> skip_whitespace
- |> parse_header_value(headers, name, value)
- }
- |> more_please_headers(data)
-
- // \r\n\r\n
- <<13, 10, 13, 10, data:bytes>> -> {
- use name <- result.try(bit_array.to_string(name))
- use value <- result.map(bit_array.to_string(value))
- let headers = list.reverse([#(string.lowercase(name), value), ..headers])
- MultipartHeaders(headers, data)
- }
-
- // \r\n\s
- // \r\n\t
- <<13, 10, 32, data:bytes>> | <<13, 10, 9, data:bytes>> ->
- parse_header_value(data, headers, name, value)
-
- // \r\n
- <<13, 10, data:bytes>> -> {
- use name <- result.try(bit_array.to_string(name))
- use value <- result.try(bit_array.to_string(value))
- let headers = [#(string.lowercase(name), value), ..headers]
- parse_header_name(data, headers, <<>>)
- }
-
- <<char, rest:bytes>> -> {
- let value = <<value:bits, char>>
- parse_header_value(rest, headers, name, value)
- }
-
- _ -> Error(Nil)
- }
-}
-
-fn more_please_headers(
- continuation: fn(BitArray) -> Result(MultipartHeaders, Nil),
- existing: BitArray,
-) -> Result(MultipartHeaders, Nil) {
- Ok(MoreRequiredForHeaders(fn(more) {
- use <- bool.guard(more == <<>>, return: Error(Nil))
- continuation(<<existing:bits, more:bits>>)
- }))
-}
-
-pub type ContentDisposition {
- ContentDisposition(String, parameters: List(#(String, String)))
-}
-
-pub fn parse_content_disposition(
- header: String,
-) -> Result(ContentDisposition, Nil) {
- parse_content_disposition_type(header, "")
-}
-
-fn parse_content_disposition_type(
- header: String,
- name: String,
-) -> Result(ContentDisposition, Nil) {
- case string.pop_grapheme(header) {
- Error(Nil) -> Ok(ContentDisposition(name, []))
-
- Ok(#(" ", rest)) | Ok(#("\t", rest)) | Ok(#(";", rest)) -> {
- let result = parse_rfc_2045_parameters(rest, [])
- use parameters <- result.map(result)
- ContentDisposition(name, parameters)
- }
-
- Ok(#(grapheme, rest)) ->
- parse_content_disposition_type(rest, name <> string.lowercase(grapheme))
- }
-}
-
-fn parse_rfc_2045_parameters(
- header: String,
- parameters: List(#(String, String)),
-) -> Result(List(#(String, String)), Nil) {
- case string.pop_grapheme(header) {
- Error(Nil) -> Ok(list.reverse(parameters))
-
- Ok(#(";", rest)) | Ok(#(" ", rest)) | Ok(#("\t", rest)) ->
- parse_rfc_2045_parameters(rest, parameters)
-
- Ok(#(grapheme, rest)) -> {
- let acc = string.lowercase(grapheme)
- use #(parameter, rest) <- result.try(parse_rfc_2045_parameter(rest, acc))
- parse_rfc_2045_parameters(rest, [parameter, ..parameters])
- }
- }
-}
-
-fn parse_rfc_2045_parameter(
- header: String,
- name: String,
-) -> Result(#(#(String, String), String), Nil) {
- use #(grapheme, rest) <- result.try(string.pop_grapheme(header))
- case grapheme {
- "=" -> parse_rfc_2045_parameter_value(rest, name)
- _ -> parse_rfc_2045_parameter(rest, name <> string.lowercase(grapheme))
- }
-}
-
-fn parse_rfc_2045_parameter_value(
- header: String,
- name: String,
-) -> Result(#(#(String, String), String), Nil) {
- case string.pop_grapheme(header) {
- Error(Nil) -> Error(Nil)
- Ok(#("\"", rest)) -> parse_rfc_2045_parameter_quoted_value(rest, name, "")
- Ok(#(grapheme, rest)) ->
- Ok(parse_rfc_2045_parameter_unquoted_value(rest, name, grapheme))
- }
-}
-
-fn parse_rfc_2045_parameter_quoted_value(
- header: String,
- name: String,
- value: String,
-) -> Result(#(#(String, String), String), Nil) {
- case string.pop_grapheme(header) {
- Error(Nil) -> Error(Nil)
- Ok(#("\"", rest)) -> Ok(#(#(name, value), rest))
- Ok(#("\\", rest)) -> {
- use #(grapheme, rest) <- result.try(string.pop_grapheme(rest))
- parse_rfc_2045_parameter_quoted_value(rest, name, value <> grapheme)
- }
- Ok(#(grapheme, rest)) ->
- parse_rfc_2045_parameter_quoted_value(rest, name, value <> grapheme)
- }
-}
-
-fn parse_rfc_2045_parameter_unquoted_value(
- header: String,
- name: String,
- value: String,
-) -> #(#(String, String), String) {
- case string.pop_grapheme(header) {
- Error(Nil) -> #(#(name, value), header)
-
- Ok(#(";", rest)) | Ok(#(" ", rest)) | Ok(#("\t", rest)) -> #(
- #(name, value),
- rest,
- )
-
- Ok(#(grapheme, rest)) ->
- parse_rfc_2045_parameter_unquoted_value(rest, name, value <> grapheme)
- }
-}
-
-fn more_please_body(
- continuation: fn(BitArray) -> Result(MultipartBody, Nil),
- chunk: BitArray,
- existing: BitArray,
-) -> Result(MultipartBody, Nil) {
- fn(more) {
- use <- bool.guard(more == <<>>, return: Error(Nil))
- continuation(<<existing:bits, more:bits>>)
- }
- |> MoreRequiredForBody(chunk, _)
- |> Ok
-}
-
-@target(erlang)
-@external(erlang, "gleam_http_native", "decode_method")
-fn do_method_from_dynamic(a: Dynamic) -> Result(Method, nil)
-
-@target(javascript)
-@external(javascript, "../gleam_http_native.mjs", "decode_method")
-fn do_method_from_dynamic(a: Dynamic) -> Result(Method, Nil)
-
-/// A HTTP header is a key-value pair. Header keys should be all lowercase
-/// characters.
-pub type Header =
- #(String, String)
diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam
deleted file mode 100644
index e9ccb55..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam/http/cookie.gleam
+++ /dev/null
@@ -1,128 +0,0 @@
-import gleam/result
-import gleam/int
-import gleam/list
-import gleam/regex
-import gleam/string
-import gleam/option.{type Option, Some}
-import gleam/http.{type Scheme}
-
-/// Policy options for the SameSite cookie attribute
-///
-/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
-pub type SameSitePolicy {
- Lax
- Strict
- None
-}
-
-fn same_site_to_string(policy) {
- case policy {
- Lax -> "Lax"
- Strict -> "Strict"
- None -> "None"
- }
-}
-
-/// Attributes of a cookie when sent to a client in the `set-cookie` header.
-pub type Attributes {
- Attributes(
- max_age: Option(Int),
- domain: Option(String),
- path: Option(String),
- secure: Bool,
- http_only: Bool,
- same_site: Option(SameSitePolicy),
- )
-}
-
-/// Helper to create sensible default attributes for a set cookie.
-///
-/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Attributes
-pub fn defaults(scheme: Scheme) {
- Attributes(
- max_age: option.None,
- domain: option.None,
- path: option.Some("/"),
- secure: scheme == http.Https,
- http_only: True,
- same_site: Some(Lax),
- )
-}
-
-const epoch = "Expires=Thu, 01 Jan 1970 00:00:00 GMT"
-
-fn cookie_attributes_to_list(attributes) {
- let Attributes(
- max_age: max_age,
- domain: domain,
- path: path,
- secure: secure,
- http_only: http_only,
- same_site: same_site,
- ) = attributes
- [
- // Expires is a deprecated attribute for cookies, it has been replaced with MaxAge
- // MaxAge is widely supported and so Expires values are not set.
- // Only when deleting cookies is the exception made to use the old format,
- // to ensure complete clearup of cookies if required by an application.
- case max_age {
- option.Some(0) -> option.Some([epoch])
- _ -> option.None
- },
- option.map(max_age, fn(max_age) { ["Max-Age=", int.to_string(max_age)] }),
- option.map(domain, fn(domain) { ["Domain=", domain] }),
- option.map(path, fn(path) { ["Path=", path] }),
- case secure {
- True -> option.Some(["Secure"])
- False -> option.None
- },
- case http_only {
- True -> option.Some(["HttpOnly"])
- False -> option.None
- },
- option.map(
- same_site,
- fn(same_site) { ["SameSite=", same_site_to_string(same_site)] },
- ),
- ]
- |> list.filter_map(option.to_result(_, Nil))
-}
-
-pub fn set_header(name: String, value: String, attributes: Attributes) -> String {
- [[name, "=", value], ..cookie_attributes_to_list(attributes)]
- |> list.map(string.join(_, ""))
- |> string.join("; ")
-}
-
-/// Parse a list of cookies from a header string. Any malformed cookies will be
-/// discarded.
-///
-pub fn parse(cookie_string: String) -> List(#(String, String)) {
- let assert Ok(re) = regex.from_string("[,;]")
- regex.split(re, cookie_string)
- |> list.filter_map(fn(pair) {
- case string.split_once(string.trim(pair), "=") {
- Ok(#("", _)) -> Error(Nil)
- Ok(#(key, value)) -> {
- let key = string.trim(key)
- let value = string.trim(value)
- use _ <- result.then(check_token(key))
- use _ <- result.then(check_token(value))
- Ok(#(key, value))
- }
- Error(Nil) -> Error(Nil)
- }
- })
-}
-
-fn check_token(token: String) -> Result(Nil, Nil) {
- case string.pop_grapheme(token) {
- Error(Nil) -> Ok(Nil)
- Ok(#(" ", _)) -> Error(Nil)
- Ok(#("\t", _)) -> Error(Nil)
- Ok(#("\r", _)) -> Error(Nil)
- Ok(#("\n", _)) -> Error(Nil)
- Ok(#("\f", _)) -> Error(Nil)
- Ok(#(_, rest)) -> check_token(rest)
- }
-}
diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam
deleted file mode 100644
index 0bf9af9..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam/http/request.gleam
+++ /dev/null
@@ -1,267 +0,0 @@
-import gleam/result
-// TODO: validate_req
-import gleam/http.{type Header, type Method, type Scheme, Get}
-import gleam/http/cookie
-import gleam/option.{type Option}
-import gleam/uri.{type Uri, Uri}
-import gleam/list
-import gleam/string
-import gleam/string_builder
-
-// TODO: document
-pub type Request(body) {
- Request(
- method: Method,
- headers: List(Header),
- body: body,
- scheme: Scheme,
- host: String,
- port: Option(Int),
- path: String,
- query: Option(String),
- )
-}
-
-/// Return the uri that a request was sent to.
-///
-pub fn to_uri(request: Request(a)) -> Uri {
- Uri(
- scheme: option.Some(http.scheme_to_string(request.scheme)),
- userinfo: option.None,
- host: option.Some(request.host),
- port: request.port,
- path: request.path,
- query: request.query,
- fragment: option.None,
- )
-}
-
-/// Construct a request from a URI.
-///
-pub fn from_uri(uri: Uri) -> Result(Request(String), Nil) {
- use scheme <- result.then(
- uri.scheme
- |> option.unwrap("")
- |> http.scheme_from_string,
- )
- use host <- result.then(
- uri.host
- |> option.to_result(Nil),
- )
- let req =
- Request(
- method: Get,
- headers: [],
- body: "",
- scheme: scheme,
- host: host,
- port: uri.port,
- path: uri.path,
- query: uri.query,
- )
- Ok(req)
-}
-
-/// Get the value for a given header.
-///
-/// If the request does not have that header then `Error(Nil)` is returned.
-///
-pub fn get_header(request: Request(body), key: String) -> Result(String, Nil) {
- list.key_find(request.headers, string.lowercase(key))
-}
-
-/// Set the header with the given value under the given header key.
-///
-/// If already present, it is replaced.
-pub fn set_header(
- request: Request(body),
- key: String,
- value: String,
-) -> Request(body) {
- let headers = list.key_set(request.headers, string.lowercase(key), value)
- Request(..request, headers: headers)
-}
-
-/// Prepend the header with the given value under the given header key.
-///
-/// Similar to `set_header` except if the header already exists it prepends
-/// another header with the same key.
-pub fn prepend_header(
- request: Request(body),
- key: String,
- value: String,
-) -> Request(body) {
- let headers = [#(string.lowercase(key), value), ..request.headers]
- Request(..request, headers: headers)
-}
-
-// TODO: record update syntax, which can't be done currently as body type changes
-/// Set the body of the request, overwriting any existing body.
-///
-pub fn set_body(req: Request(old_body), body: new_body) -> Request(new_body) {
- let Request(
- method: method,
- headers: headers,
- scheme: scheme,
- host: host,
- port: port,
- path: path,
- query: query,
- ..,
- ) = req
- Request(
- method: method,
- headers: headers,
- body: body,
- scheme: scheme,
- host: host,
- port: port,
- path: path,
- query: query,
- )
-}
-
-/// Update the body of a request using a given function.
-///
-pub fn map(
- request: Request(old_body),
- transform: fn(old_body) -> new_body,
-) -> Request(new_body) {
- request.body
- |> transform
- |> set_body(request, _)
-}
-
-/// Return the non-empty segments of a request path.
-///
-/// # Examples
-///
-/// ```gleam
-/// > new()
-/// > |> set_path("/one/two/three")
-/// > |> path_segments
-/// ["one", "two", "three"]
-/// ```
-///
-pub fn path_segments(request: Request(body)) -> List(String) {
- request.path
- |> uri.path_segments
-}
-
-/// Decode the query of a request.
-pub fn get_query(request: Request(body)) -> Result(List(#(String, String)), Nil) {
- case request.query {
- option.Some(query_string) -> uri.parse_query(query_string)
- option.None -> Ok([])
- }
-}
-
-// TODO: escape
-/// Set the query of the request.
-///
-pub fn set_query(
- req: Request(body),
- query: List(#(String, String)),
-) -> Request(body) {
- let pair = fn(t: #(String, String)) {
- string_builder.from_strings([t.0, "=", t.1])
- }
- let query =
- query
- |> list.map(pair)
- |> list.intersperse(string_builder.from_string("&"))
- |> string_builder.concat
- |> string_builder.to_string
- |> option.Some
- Request(..req, query: query)
-}
-
-/// Set the method of the request.
-///
-pub fn set_method(req: Request(body), method: Method) -> Request(body) {
- Request(..req, method: method)
-}
-
-/// A request with commonly used default values. This request can be used as
-/// an initial value and then update to create the desired request.
-///
-pub fn new() -> Request(String) {
- Request(
- method: Get,
- headers: [],
- body: "",
- scheme: http.Https,
- host: "localhost",
- port: option.None,
- path: "",
- query: option.None,
- )
-}
-
-/// Construct a request from a URL string
-///
-pub fn to(url: String) -> Result(Request(String), Nil) {
- url
- |> uri.parse
- |> result.then(from_uri)
-}
-
-/// Set the scheme (protocol) of the request.
-///
-pub fn set_scheme(req: Request(body), scheme: Scheme) -> Request(body) {
- Request(..req, scheme: scheme)
-}
-
-/// Set the method of the request.
-///
-pub fn set_host(req: Request(body), host: String) -> Request(body) {
- Request(..req, host: host)
-}
-
-/// Set the port of the request.
-///
-pub fn set_port(req: Request(body), port: Int) -> Request(body) {
- Request(..req, port: option.Some(port))
-}
-
-/// Set the path of the request.
-///
-pub fn set_path(req: Request(body), path: String) -> Request(body) {
- Request(..req, path: path)
-}
-
-/// Send a cookie with a request
-///
-/// Multiple cookies are added to the same cookie header.
-pub fn set_cookie(req: Request(body), name: String, value: String) {
- let new_cookie_string = string.join([name, value], "=")
-
- let #(cookies_string, headers) = case list.key_pop(req.headers, "cookie") {
- Ok(#(cookies_string, headers)) -> {
- let cookies_string =
- string.join([cookies_string, new_cookie_string], "; ")
- #(cookies_string, headers)
- }
- Error(Nil) -> #(new_cookie_string, req.headers)
- }
-
- Request(..req, headers: [#("cookie", cookies_string), ..headers])
-}
-
-/// Fetch the cookies sent in a request.
-///
-/// Note badly formed cookie pairs will be ignored.
-/// RFC6265 specifies that invalid cookie names/attributes should be ignored.
-pub fn get_cookies(req) -> List(#(String, String)) {
- let Request(headers: headers, ..) = req
-
- headers
- |> list.filter_map(fn(header) {
- let #(name, value) = header
- case name {
- "cookie" -> Ok(cookie.parse(value))
- _ -> Error(Nil)
- }
- })
- |> list.flatten()
-}
diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam
deleted file mode 100644
index 87f9140..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam/http/response.gleam
+++ /dev/null
@@ -1,141 +0,0 @@
-import gleam/result
-import gleam/http.{type Header}
-import gleam/http/cookie
-import gleam/list
-import gleam/string
-import gleam/option
-
-// TODO: document
-pub type Response(body) {
- Response(status: Int, headers: List(Header), body: body)
-}
-
-/// Update the body of a response using a given result returning function.
-///
-/// If the given function returns an `Ok` value the body is set, if it returns
-/// an `Error` value then the error is returned.
-///
-pub fn try_map(
- response: Response(old_body),
- transform: fn(old_body) -> Result(new_body, error),
-) -> Result(Response(new_body), error) {
- use body <- result.then(transform(response.body))
- Ok(set_body(response, body))
-}
-
-/// Construct an empty Response.
-///
-/// The body type of the returned response is `String` and could be set with a
-/// call to `set_body`.
-///
-pub fn new(status: Int) -> Response(String) {
- Response(status: status, headers: [], body: "")
-}
-
-/// Get the value for a given header.
-///
-/// If the response does not have that header then `Error(Nil)` is returned.
-///
-pub fn get_header(response: Response(body), key: String) -> Result(String, Nil) {
- list.key_find(response.headers, string.lowercase(key))
-}
-
-/// Set the header with the given value under the given header key.
-///
-/// If the response already has that key, it is replaced.
-pub fn set_header(
- response: Response(body),
- key: String,
- value: String,
-) -> Response(body) {
- let headers = list.key_set(response.headers, string.lowercase(key), value)
- Response(..response, headers: headers)
-}
-
-/// Prepend the header with the given value under the given header key.
-///
-/// Similar to `set_header` except if the header already exists it prepends
-/// another header with the same key.
-pub fn prepend_header(
- response: Response(body),
- key: String,
- value: String,
-) -> Response(body) {
- let headers = [#(string.lowercase(key), value), ..response.headers]
- Response(..response, headers: headers)
-}
-
-/// Set the body of the response, overwriting any existing body.
-///
-pub fn set_body(
- response: Response(old_body),
- body: new_body,
-) -> Response(new_body) {
- let Response(status: status, headers: headers, ..) = response
- Response(status: status, headers: headers, body: body)
-}
-
-/// Update the body of a response using a given function.
-///
-pub fn map(
- response: Response(old_body),
- transform: fn(old_body) -> new_body,
-) -> Response(new_body) {
- response.body
- |> transform
- |> set_body(response, _)
-}
-
-/// Create a response that redirects to the given uri.
-///
-pub fn redirect(uri: String) -> Response(String) {
- Response(
- status: 303,
- headers: [#("location", uri)],
- body: string.append("You are being redirected to ", uri),
- )
-}
-
-/// Fetch the cookies sent in a response.
-///
-/// Badly formed cookies will be discarded.
-///
-pub fn get_cookies(resp) -> List(#(String, String)) {
- let Response(headers: headers, ..) = resp
- headers
- |> list.filter_map(fn(header) {
- let #(name, value) = header
- case name {
- "set-cookie" -> Ok(cookie.parse(value))
- _ -> Error(Nil)
- }
- })
- |> list.flatten()
-}
-
-/// Set a cookie value for a client
-///
-pub fn set_cookie(
- response: Response(t),
- name: String,
- value: String,
- attributes: cookie.Attributes,
-) -> Response(t) {
- prepend_header(
- response,
- "set-cookie",
- cookie.set_header(name, value, attributes),
- )
-}
-
-/// Expire a cookie value for a client
-///
-/// Note: The attributes value should be the same as when the response cookie was set.
-pub fn expire_cookie(
- response: Response(t),
- name: String,
- attributes: cookie.Attributes,
-) -> Response(t) {
- let attrs = cookie.Attributes(..attributes, max_age: option.Some(0))
- set_cookie(response, name, "", attrs)
-}
diff --git a/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam b/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam
deleted file mode 100644
index 3dfac87..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam/http/service.gleam
+++ /dev/null
@@ -1,82 +0,0 @@
-import gleam/http.{Delete, Patch, Post, Put}
-import gleam/http/request.{type Request}
-import gleam/http/response.{type Response}
-import gleam/list
-import gleam/result
-
-// TODO: document
-pub type Service(in, out) =
- fn(Request(in)) -> Response(out)
-
-pub type Middleware(before_req, before_resp, after_req, after_resp) =
- fn(Service(before_req, before_resp)) -> Service(after_req, after_resp)
-
-/// A middleware that transform the response body returned by the service using
-/// a given function.
-///
-pub fn map_response_body(
- service: Service(req, a),
- with mapper: fn(a) -> b,
-) -> Service(req, b) {
- fn(req) {
- req
- |> service
- |> response.map(mapper)
- }
-}
-
-/// A middleware that prepends a header to the request.
-///
-pub fn prepend_response_header(
- service: Service(req, resp),
- key: String,
- value: String,
-) -> Service(req, resp) {
- fn(req) {
- req
- |> service
- |> response.prepend_header(key, value)
- }
-}
-
-fn ensure_post(req: Request(a)) {
- case req.method {
- Post -> Ok(req)
- _ -> Error(Nil)
- }
-}
-
-fn get_override_method(request: Request(t)) -> Result(http.Method, Nil) {
- use query_params <- result.then(request.get_query(request))
- use method <- result.then(list.key_find(query_params, "_method"))
- use method <- result.then(http.parse_method(method))
- case method {
- Put | Patch | Delete -> Ok(method)
- _ -> Error(Nil)
- }
-}
-
-/// A middleware that overrides an incoming POST request with a method given in
-/// the request's `_method` query paramerter. This is useful as web browsers
-/// typically only support GET and POST requests, but our application may
-/// expect other HTTP methods that are more semantically correct.
-///
-/// The methods PUT, PATCH, and DELETE are accepted for overriding, all others
-/// are ignored.
-///
-/// The `_method` query paramerter can be specified in a HTML form like so:
-///
-/// <form method="POST" action="/item/1?_method=DELETE">
-/// <button type="submit">Delete item</button>
-/// </form>
-///
-pub fn method_override(service: Service(req, resp)) -> Service(req, resp) {
- fn(request) {
- request
- |> ensure_post
- |> result.then(get_override_method)
- |> result.map(request.set_method(request, _))
- |> result.unwrap(request)
- |> service
- }
-}
diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http.erl b/aoc2023/build/packages/gleam_http/src/gleam@http.erl
deleted file mode 100644
index 91ee6e8..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam@http.erl
+++ /dev/null
@@ -1,626 +0,0 @@
--module(gleam@http).
--compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-
--export([parse_method/1, method_to_string/1, scheme_to_string/1, scheme_from_string/1, parse_content_disposition/1, parse_multipart_body/2, method_from_dynamic/1, parse_multipart_headers/2]).
--export_type([method/0, scheme/0, multipart_headers/0, multipart_body/0, content_disposition/0]).
-
--type method() :: get |
- post |
- head |
- put |
- delete |
- trace |
- connect |
- options |
- patch |
- {other, binary()}.
-
--type scheme() :: http | https.
-
--type multipart_headers() :: {multipart_headers,
- list({binary(), binary()}),
- bitstring()} |
- {more_required_for_headers,
- fun((bitstring()) -> {ok, multipart_headers()} | {error, nil})}.
-
--type multipart_body() :: {multipart_body, bitstring(), boolean(), bitstring()} |
- {more_required_for_body,
- bitstring(),
- fun((bitstring()) -> {ok, multipart_body()} | {error, nil})}.
-
--type content_disposition() :: {content_disposition,
- binary(),
- list({binary(), binary()})}.
-
--spec parse_method(binary()) -> {ok, method()} | {error, nil}.
-parse_method(S) ->
- case gleam@string:lowercase(S) of
- <<"connect"/utf8>> ->
- {ok, connect};
-
- <<"delete"/utf8>> ->
- {ok, delete};
-
- <<"get"/utf8>> ->
- {ok, get};
-
- <<"head"/utf8>> ->
- {ok, head};
-
- <<"options"/utf8>> ->
- {ok, options};
-
- <<"patch"/utf8>> ->
- {ok, patch};
-
- <<"post"/utf8>> ->
- {ok, post};
-
- <<"put"/utf8>> ->
- {ok, put};
-
- <<"trace"/utf8>> ->
- {ok, trace};
-
- _ ->
- {error, nil}
- end.
-
--spec method_to_string(method()) -> binary().
-method_to_string(Method) ->
- case Method of
- connect ->
- <<"connect"/utf8>>;
-
- delete ->
- <<"delete"/utf8>>;
-
- get ->
- <<"get"/utf8>>;
-
- head ->
- <<"head"/utf8>>;
-
- options ->
- <<"options"/utf8>>;
-
- patch ->
- <<"patch"/utf8>>;
-
- post ->
- <<"post"/utf8>>;
-
- put ->
- <<"put"/utf8>>;
-
- trace ->
- <<"trace"/utf8>>;
-
- {other, S} ->
- S
- end.
-
--spec scheme_to_string(scheme()) -> binary().
-scheme_to_string(Scheme) ->
- case Scheme of
- http ->
- <<"http"/utf8>>;
-
- https ->
- <<"https"/utf8>>
- end.
-
--spec scheme_from_string(binary()) -> {ok, scheme()} | {error, nil}.
-scheme_from_string(Scheme) ->
- case gleam@string:lowercase(Scheme) of
- <<"http"/utf8>> ->
- {ok, http};
-
- <<"https"/utf8>> ->
- {ok, https};
-
- _ ->
- {error, nil}
- end.
-
--spec skip_whitespace(bitstring()) -> bitstring().
-skip_whitespace(Data) ->
- case Data of
- <<32, Data@1/binary>> ->
- skip_whitespace(Data@1);
-
- <<9, Data@1/binary>> ->
- skip_whitespace(Data@1);
-
- _ ->
- Data
- end.
-
--spec more_please_headers(
- fun((bitstring()) -> {ok, multipart_headers()} | {error, nil}),
- bitstring()
-) -> {ok, multipart_headers()} | {error, nil}.
-more_please_headers(Continuation, Existing) ->
- {ok,
- {more_required_for_headers,
- fun(More) ->
- gleam@bool:guard(
- More =:= <<>>,
- {error, nil},
- fun() ->
- Continuation(<<Existing/bitstring, More/bitstring>>)
- end
- )
- end}}.
-
--spec parse_rfc_2045_parameter_quoted_value(binary(), binary(), binary()) -> {ok,
- {{binary(), binary()}, binary()}} |
- {error, nil}.
-parse_rfc_2045_parameter_quoted_value(Header, Name, Value) ->
- case gleam@string:pop_grapheme(Header) of
- {error, nil} ->
- {error, nil};
-
- {ok, {<<"\""/utf8>>, Rest}} ->
- {ok, {{Name, Value}, Rest}};
-
- {ok, {<<"\\"/utf8>>, Rest@1}} ->
- gleam@result:'try'(
- gleam@string:pop_grapheme(Rest@1),
- fun(_use0) ->
- {Grapheme, Rest@2} = _use0,
- parse_rfc_2045_parameter_quoted_value(
- Rest@2,
- Name,
- <<Value/binary, Grapheme/binary>>
- )
- end
- );
-
- {ok, {Grapheme@1, Rest@3}} ->
- parse_rfc_2045_parameter_quoted_value(
- Rest@3,
- Name,
- <<Value/binary, Grapheme@1/binary>>
- )
- end.
-
--spec parse_rfc_2045_parameter_unquoted_value(binary(), binary(), binary()) -> {{binary(),
- binary()},
- binary()}.
-parse_rfc_2045_parameter_unquoted_value(Header, Name, Value) ->
- case gleam@string:pop_grapheme(Header) of
- {error, nil} ->
- {{Name, Value}, Header};
-
- {ok, {<<";"/utf8>>, Rest}} ->
- {{Name, Value}, Rest};
-
- {ok, {<<" "/utf8>>, Rest}} ->
- {{Name, Value}, Rest};
-
- {ok, {<<"\t"/utf8>>, Rest}} ->
- {{Name, Value}, Rest};
-
- {ok, {Grapheme, Rest@1}} ->
- parse_rfc_2045_parameter_unquoted_value(
- Rest@1,
- Name,
- <<Value/binary, Grapheme/binary>>
- )
- end.
-
--spec parse_rfc_2045_parameter_value(binary(), binary()) -> {ok,
- {{binary(), binary()}, binary()}} |
- {error, nil}.
-parse_rfc_2045_parameter_value(Header, Name) ->
- case gleam@string:pop_grapheme(Header) of
- {error, nil} ->
- {error, nil};
-
- {ok, {<<"\""/utf8>>, Rest}} ->
- parse_rfc_2045_parameter_quoted_value(Rest, Name, <<""/utf8>>);
-
- {ok, {Grapheme, Rest@1}} ->
- {ok,
- parse_rfc_2045_parameter_unquoted_value(Rest@1, Name, Grapheme)}
- end.
-
--spec parse_rfc_2045_parameter(binary(), binary()) -> {ok,
- {{binary(), binary()}, binary()}} |
- {error, nil}.
-parse_rfc_2045_parameter(Header, Name) ->
- gleam@result:'try'(
- gleam@string:pop_grapheme(Header),
- fun(_use0) ->
- {Grapheme, Rest} = _use0,
- case Grapheme of
- <<"="/utf8>> ->
- parse_rfc_2045_parameter_value(Rest, Name);
-
- _ ->
- parse_rfc_2045_parameter(
- Rest,
- <<Name/binary,
- (gleam@string:lowercase(Grapheme))/binary>>
- )
- end
- end
- ).
-
--spec parse_rfc_2045_parameters(binary(), list({binary(), binary()})) -> {ok,
- list({binary(), binary()})} |
- {error, nil}.
-parse_rfc_2045_parameters(Header, Parameters) ->
- case gleam@string:pop_grapheme(Header) of
- {error, nil} ->
- {ok, gleam@list:reverse(Parameters)};
-
- {ok, {<<";"/utf8>>, Rest}} ->
- parse_rfc_2045_parameters(Rest, Parameters);
-
- {ok, {<<" "/utf8>>, Rest}} ->
- parse_rfc_2045_parameters(Rest, Parameters);
-
- {ok, {<<"\t"/utf8>>, Rest}} ->
- parse_rfc_2045_parameters(Rest, Parameters);
-
- {ok, {Grapheme, Rest@1}} ->
- Acc = gleam@string:lowercase(Grapheme),
- gleam@result:'try'(
- parse_rfc_2045_parameter(Rest@1, Acc),
- fun(_use0) ->
- {Parameter, Rest@2} = _use0,
- parse_rfc_2045_parameters(Rest@2, [Parameter | Parameters])
- end
- )
- end.
-
--spec parse_content_disposition_type(binary(), binary()) -> {ok,
- content_disposition()} |
- {error, nil}.
-parse_content_disposition_type(Header, Name) ->
- case gleam@string:pop_grapheme(Header) of
- {error, nil} ->
- {ok, {content_disposition, Name, []}};
-
- {ok, {<<" "/utf8>>, Rest}} ->
- Result = parse_rfc_2045_parameters(Rest, []),
- gleam@result:map(
- Result,
- fun(Parameters) -> {content_disposition, Name, Parameters} end
- );
-
- {ok, {<<"\t"/utf8>>, Rest}} ->
- Result = parse_rfc_2045_parameters(Rest, []),
- gleam@result:map(
- Result,
- fun(Parameters) -> {content_disposition, Name, Parameters} end
- );
-
- {ok, {<<";"/utf8>>, Rest}} ->
- Result = parse_rfc_2045_parameters(Rest, []),
- gleam@result:map(
- Result,
- fun(Parameters) -> {content_disposition, Name, Parameters} end
- );
-
- {ok, {Grapheme, Rest@1}} ->
- parse_content_disposition_type(
- Rest@1,
- <<Name/binary, (gleam@string:lowercase(Grapheme))/binary>>
- )
- end.
-
--spec parse_content_disposition(binary()) -> {ok, content_disposition()} |
- {error, nil}.
-parse_content_disposition(Header) ->
- parse_content_disposition_type(Header, <<""/utf8>>).
-
--spec more_please_body(
- fun((bitstring()) -> {ok, multipart_body()} | {error, nil}),
- bitstring(),
- bitstring()
-) -> {ok, multipart_body()} | {error, nil}.
-more_please_body(Continuation, Chunk, Existing) ->
- _pipe = fun(More) ->
- gleam@bool:guard(
- More =:= <<>>,
- {error, nil},
- fun() -> Continuation(<<Existing/bitstring, More/bitstring>>) end
- )
- end,
- _pipe@1 = {more_required_for_body, Chunk, _pipe},
- {ok, _pipe@1}.
-
--spec parse_body_loop(bitstring(), bitstring(), bitstring()) -> {ok,
- multipart_body()} |
- {error, nil}.
-parse_body_loop(Data, Boundary, Body) ->
- Dsize = erlang:byte_size(Data),
- Bsize = erlang:byte_size(Boundary),
- Required = 6 + Bsize,
- case Data of
- _ when Dsize < Required ->
- more_please_body(
- fun(_capture) -> parse_body_loop(_capture, Boundary, <<>>) end,
- Body,
- Data
- );
-
- <<13, 10, Data@1/binary>> ->
- Desired = <<45, 45, Boundary/bitstring>>,
- Size = erlang:byte_size(Desired),
- Dsize@1 = erlang:byte_size(Data@1),
- Prefix = gleam_stdlib:bit_array_slice(Data@1, 0, Size),
- Rest = gleam_stdlib:bit_array_slice(Data@1, Size, Dsize@1 - Size),
- case {Prefix =:= {ok, Desired}, Rest} of
- {true, {ok, <<13, 10, _/binary>>}} ->
- {ok, {multipart_body, Body, false, Data@1}};
-
- {true, {ok, <<45, 45, Data@2/binary>>}} ->
- {ok, {multipart_body, Body, true, Data@2}};
-
- {false, _} ->
- parse_body_loop(
- Data@1,
- Boundary,
- <<Body/bitstring, 13, 10>>
- );
-
- {_, _} ->
- {error, nil}
- end;
-
- <<Char, Data@3/binary>> ->
- parse_body_loop(Data@3, Boundary, <<Body/bitstring, Char>>)
- end.
-
--spec parse_body_with_bit_array(bitstring(), bitstring()) -> {ok,
- multipart_body()} |
- {error, nil}.
-parse_body_with_bit_array(Data, Boundary) ->
- Bsize = erlang:byte_size(Boundary),
- Prefix = gleam_stdlib:bit_array_slice(Data, 0, 2 + Bsize),
- case Prefix =:= {ok, <<45, 45, Boundary/bitstring>>} of
- true ->
- {ok, {multipart_body, <<>>, false, Data}};
-
- false ->
- parse_body_loop(Data, Boundary, <<>>)
- end.
-
--spec parse_multipart_body(bitstring(), binary()) -> {ok, multipart_body()} |
- {error, nil}.
-parse_multipart_body(Data, Boundary) ->
- _pipe = Boundary,
- _pipe@1 = gleam_stdlib:identity(_pipe),
- parse_body_with_bit_array(Data, _pipe@1).
-
--spec method_from_dynamic(gleam@dynamic:dynamic_()) -> {ok, method()} |
- {error, list(gleam@dynamic:decode_error())}.
-method_from_dynamic(Value) ->
- case gleam_http_native:decode_method(Value) of
- {ok, Method} ->
- {ok, Method};
-
- {error, _} ->
- {error,
- [{decode_error,
- <<"HTTP method"/utf8>>,
- gleam@dynamic:classify(Value),
- []}]}
- end.
-
--spec parse_header_value(
- bitstring(),
- list({binary(), binary()}),
- bitstring(),
- bitstring()
-) -> {ok, multipart_headers()} | {error, nil}.
-parse_header_value(Data, Headers, Name, Value) ->
- Size = erlang:byte_size(Data),
- case Data of
- _ when Size < 4 ->
- _pipe@2 = fun(Data@1) -> _pipe = Data@1,
- _pipe@1 = skip_whitespace(_pipe),
- parse_header_value(_pipe@1, Headers, Name, Value) end,
- more_please_headers(_pipe@2, Data);
-
- <<13, 10, 13, 10, Data@2/binary>> ->
- gleam@result:'try'(
- gleam@bit_array:to_string(Name),
- fun(Name@1) ->
- gleam@result:map(
- gleam@bit_array:to_string(Value),
- fun(Value@1) ->
- Headers@1 = gleam@list:reverse(
- [{gleam@string:lowercase(Name@1), Value@1} |
- Headers]
- ),
- {multipart_headers, Headers@1, Data@2}
- end
- )
- end
- );
-
- <<13, 10, 32, Data@3/binary>> ->
- parse_header_value(Data@3, Headers, Name, Value);
-
- <<13, 10, 9, Data@3/binary>> ->
- parse_header_value(Data@3, Headers, Name, Value);
-
- <<13, 10, Data@4/binary>> ->
- gleam@result:'try'(
- gleam@bit_array:to_string(Name),
- fun(Name@2) ->
- gleam@result:'try'(
- gleam@bit_array:to_string(Value),
- fun(Value@2) ->
- Headers@2 = [{gleam@string:lowercase(Name@2),
- Value@2} |
- Headers],
- parse_header_name(Data@4, Headers@2, <<>>)
- end
- )
- end
- );
-
- <<Char, Rest/binary>> ->
- Value@3 = <<Value/bitstring, Char>>,
- parse_header_value(Rest, Headers, Name, Value@3);
-
- _ ->
- {error, nil}
- end.
-
--spec parse_header_name(bitstring(), list({binary(), binary()}), bitstring()) -> {ok,
- multipart_headers()} |
- {error, nil}.
-parse_header_name(Data, Headers, Name) ->
- case skip_whitespace(Data) of
- <<58, Data@1/binary>> ->
- _pipe = Data@1,
- _pipe@1 = skip_whitespace(_pipe),
- parse_header_value(_pipe@1, Headers, Name, <<>>);
-
- <<Char, Data@2/binary>> ->
- parse_header_name(Data@2, Headers, <<Name/bitstring, Char>>);
-
- <<>> ->
- more_please_headers(
- fun(_capture) -> parse_header_name(_capture, Headers, Name) end,
- Data
- )
- end.
-
--spec do_parse_headers(bitstring()) -> {ok, multipart_headers()} | {error, nil}.
-do_parse_headers(Data) ->
- case Data of
- <<13, 10, 13, 10, Data@1/binary>> ->
- {ok, {multipart_headers, [], Data@1}};
-
- <<13, 10, Data@2/binary>> ->
- parse_header_name(Data@2, [], <<>>);
-
- <<13>> ->
- more_please_headers(fun do_parse_headers/1, Data);
-
- <<>> ->
- more_please_headers(fun do_parse_headers/1, Data);
-
- _ ->
- {error, nil}
- end.
-
--spec parse_headers_after_prelude(bitstring(), bitstring()) -> {ok,
- multipart_headers()} |
- {error, nil}.
-parse_headers_after_prelude(Data, Boundary) ->
- Dsize = erlang:byte_size(Data),
- Bsize = erlang:byte_size(Boundary),
- Required_size = Bsize + 4,
- gleam@bool:guard(
- Dsize < Required_size,
- more_please_headers(
- fun(_capture) -> parse_headers_after_prelude(_capture, Boundary) end,
- Data
- ),
- fun() ->
- gleam@result:'try'(
- gleam_stdlib:bit_array_slice(Data, 0, Required_size - 2),
- fun(Prefix) ->
- gleam@result:'try'(
- gleam_stdlib:bit_array_slice(Data, 2 + Bsize, 2),
- fun(Second) ->
- Desired = <<45, 45, Boundary/bitstring>>,
- gleam@bool:guard(
- Prefix /= Desired,
- {error, nil},
- fun() -> case Second =:= <<45, 45>> of
- true ->
- Rest_size = Dsize - Required_size,
- gleam@result:map(
- gleam_stdlib:bit_array_slice(
- Data,
- Required_size,
- Rest_size
- ),
- fun(Data@1) ->
- {multipart_headers,
- [],
- Data@1}
- end
- );
-
- false ->
- Start = Required_size - 2,
- Rest_size@1 = (Dsize - Required_size)
- + 2,
- gleam@result:'try'(
- gleam_stdlib:bit_array_slice(
- Data,
- Start,
- Rest_size@1
- ),
- fun(Data@2) ->
- do_parse_headers(Data@2)
- end
- )
- end end
- )
- end
- )
- end
- )
- end
- ).
-
--spec skip_preamble(bitstring(), bitstring()) -> {ok, multipart_headers()} |
- {error, nil}.
-skip_preamble(Data, Boundary) ->
- Data_size = erlang:byte_size(Data),
- Boundary_size = erlang:byte_size(Boundary),
- Required = Boundary_size + 4,
- case Data of
- _ when Data_size < Required ->
- more_please_headers(
- fun(_capture) -> skip_preamble(_capture, Boundary) end,
- Data
- );
-
- <<13, 10, 45, 45, Data@1/binary>> ->
- case gleam_stdlib:bit_array_slice(Data@1, 0, Boundary_size) of
- {ok, Prefix} when Prefix =:= Boundary ->
- Start = Boundary_size,
- Length = erlang:byte_size(Data@1) - Boundary_size,
- gleam@result:'try'(
- gleam_stdlib:bit_array_slice(Data@1, Start, Length),
- fun(Rest) -> do_parse_headers(Rest) end
- );
-
- {ok, _} ->
- skip_preamble(Data@1, Boundary);
-
- {error, _} ->
- {error, nil}
- end;
-
- <<_, Data@2/binary>> ->
- skip_preamble(Data@2, Boundary)
- end.
-
--spec parse_multipart_headers(bitstring(), binary()) -> {ok,
- multipart_headers()} |
- {error, nil}.
-parse_multipart_headers(Data, Boundary) ->
- Boundary@1 = gleam_stdlib:identity(Boundary),
- Prefix = <<45, 45, Boundary@1/bitstring>>,
- case gleam_stdlib:bit_array_slice(Data, 0, erlang:byte_size(Prefix)) =:= {ok,
- Prefix} of
- true ->
- parse_headers_after_prelude(Data, Boundary@1);
-
- false ->
- skip_preamble(Data, Boundary@1)
- end.
diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl
deleted file mode 100644
index 9d6d13e..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam@http@cookie.erl
+++ /dev/null
@@ -1,153 +0,0 @@
--module(gleam@http@cookie).
--compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-
--export([defaults/1, set_header/3, parse/1]).
--export_type([same_site_policy/0, attributes/0]).
-
--type same_site_policy() :: lax | strict | none.
-
--type attributes() :: {attributes,
- gleam@option:option(integer()),
- gleam@option:option(binary()),
- gleam@option:option(binary()),
- boolean(),
- boolean(),
- gleam@option:option(same_site_policy())}.
-
--spec same_site_to_string(same_site_policy()) -> binary().
-same_site_to_string(Policy) ->
- case Policy of
- lax ->
- <<"Lax"/utf8>>;
-
- strict ->
- <<"Strict"/utf8>>;
-
- none ->
- <<"None"/utf8>>
- end.
-
--spec defaults(gleam@http:scheme()) -> attributes().
-defaults(Scheme) ->
- {attributes,
- none,
- none,
- {some, <<"/"/utf8>>},
- Scheme =:= https,
- true,
- {some, lax}}.
-
--spec cookie_attributes_to_list(attributes()) -> list(list(binary())).
-cookie_attributes_to_list(Attributes) ->
- {attributes, Max_age, Domain, Path, Secure, Http_only, Same_site} = Attributes,
- _pipe = [case Max_age of
- {some, 0} ->
- {some, [<<"Expires=Thu, 01 Jan 1970 00:00:00 GMT"/utf8>>]};
-
- _ ->
- none
- end, gleam@option:map(
- Max_age,
- fun(Max_age@1) ->
- [<<"Max-Age="/utf8>>, gleam@int:to_string(Max_age@1)]
- end
- ), gleam@option:map(
- Domain,
- fun(Domain@1) -> [<<"Domain="/utf8>>, Domain@1] end
- ), gleam@option:map(Path, fun(Path@1) -> [<<"Path="/utf8>>, Path@1] end), case Secure of
- true ->
- {some, [<<"Secure"/utf8>>]};
-
- false ->
- none
- end, case Http_only of
- true ->
- {some, [<<"HttpOnly"/utf8>>]};
-
- false ->
- none
- end, gleam@option:map(
- Same_site,
- fun(Same_site@1) ->
- [<<"SameSite="/utf8>>, same_site_to_string(Same_site@1)]
- end
- )],
- gleam@list:filter_map(
- _pipe,
- fun(_capture) -> gleam@option:to_result(_capture, nil) end
- ).
-
--spec set_header(binary(), binary(), attributes()) -> binary().
-set_header(Name, Value, Attributes) ->
- _pipe = [[Name, <<"="/utf8>>, Value] |
- cookie_attributes_to_list(Attributes)],
- _pipe@1 = gleam@list:map(
- _pipe,
- fun(_capture) -> gleam@string:join(_capture, <<""/utf8>>) end
- ),
- gleam@string:join(_pipe@1, <<"; "/utf8>>).
-
--spec check_token(binary()) -> {ok, nil} | {error, nil}.
-check_token(Token) ->
- case gleam@string:pop_grapheme(Token) of
- {error, nil} ->
- {ok, nil};
-
- {ok, {<<" "/utf8>>, _}} ->
- {error, nil};
-
- {ok, {<<"\t"/utf8>>, _}} ->
- {error, nil};
-
- {ok, {<<"\r"/utf8>>, _}} ->
- {error, nil};
-
- {ok, {<<"\n"/utf8>>, _}} ->
- {error, nil};
-
- {ok, {<<"\f"/utf8>>, _}} ->
- {error, nil};
-
- {ok, {_, Rest}} ->
- check_token(Rest)
- end.
-
--spec parse(binary()) -> list({binary(), binary()}).
-parse(Cookie_string) ->
- _assert_subject = gleam@regex:from_string(<<"[,;]"/utf8>>),
- {ok, Re} = case _assert_subject of
- {ok, _} -> _assert_subject;
- _assert_fail ->
- erlang:error(#{gleam_error => let_assert,
- message => <<"Assertion pattern match failed"/utf8>>,
- value => _assert_fail,
- module => <<"gleam/http/cookie"/utf8>>,
- function => <<"parse"/utf8>>,
- line => 101})
- end,
- _pipe = gleam@regex:split(Re, Cookie_string),
- gleam@list:filter_map(
- _pipe,
- fun(Pair) ->
- case gleam@string:split_once(gleam@string:trim(Pair), <<"="/utf8>>) of
- {ok, {<<""/utf8>>, _}} ->
- {error, nil};
-
- {ok, {Key, Value}} ->
- Key@1 = gleam@string:trim(Key),
- Value@1 = gleam@string:trim(Value),
- gleam@result:then(
- check_token(Key@1),
- fun(_) ->
- gleam@result:then(
- check_token(Value@1),
- fun(_) -> {ok, {Key@1, Value@1}} end
- )
- end
- );
-
- {error, nil} ->
- {error, nil}
- end
- end
- ).
diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl
deleted file mode 100644
index 630788d..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam@http@request.erl
+++ /dev/null
@@ -1,202 +0,0 @@
--module(gleam@http@request).
--compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-
--export([to_uri/1, from_uri/1, get_header/2, set_header/3, prepend_header/3, set_body/2, map/2, path_segments/1, get_query/1, set_query/2, set_method/2, new/0, to/1, set_scheme/2, set_host/2, set_port/2, set_path/2, set_cookie/3, get_cookies/1]).
--export_type([request/1]).
-
--type request(FYJ) :: {request,
- gleam@http:method(),
- list({binary(), binary()}),
- FYJ,
- gleam@http:scheme(),
- binary(),
- gleam@option:option(integer()),
- binary(),
- gleam@option:option(binary())}.
-
--spec to_uri(request(any())) -> gleam@uri:uri().
-to_uri(Request) ->
- {uri,
- {some, gleam@http:scheme_to_string(erlang:element(5, Request))},
- none,
- {some, erlang:element(6, Request)},
- erlang:element(7, Request),
- erlang:element(8, Request),
- erlang:element(9, Request),
- none}.
-
--spec from_uri(gleam@uri:uri()) -> {ok, request(binary())} | {error, nil}.
-from_uri(Uri) ->
- gleam@result:then(
- begin
- _pipe = erlang:element(2, Uri),
- _pipe@1 = gleam@option:unwrap(_pipe, <<""/utf8>>),
- gleam@http:scheme_from_string(_pipe@1)
- end,
- fun(Scheme) ->
- gleam@result:then(
- begin
- _pipe@2 = erlang:element(4, Uri),
- gleam@option:to_result(_pipe@2, nil)
- end,
- fun(Host) ->
- Req = {request,
- get,
- [],
- <<""/utf8>>,
- Scheme,
- Host,
- erlang:element(5, Uri),
- erlang:element(6, Uri),
- erlang:element(7, Uri)},
- {ok, Req}
- end
- )
- end
- ).
-
--spec get_header(request(any()), binary()) -> {ok, binary()} | {error, nil}.
-get_header(Request, Key) ->
- gleam@list:key_find(erlang:element(3, Request), gleam@string:lowercase(Key)).
-
--spec set_header(request(FYT), binary(), binary()) -> request(FYT).
-set_header(Request, Key, Value) ->
- Headers = gleam@list:key_set(
- erlang:element(3, Request),
- gleam@string:lowercase(Key),
- Value
- ),
- erlang:setelement(3, Request, Headers).
-
--spec prepend_header(request(FYW), binary(), binary()) -> request(FYW).
-prepend_header(Request, Key, Value) ->
- Headers = [{gleam@string:lowercase(Key), Value} |
- erlang:element(3, Request)],
- erlang:setelement(3, Request, Headers).
-
--spec set_body(request(any()), FZB) -> request(FZB).
-set_body(Req, Body) ->
- {request, Method, Headers, _, Scheme, Host, Port, Path, Query} = Req,
- {request, Method, Headers, Body, Scheme, Host, Port, Path, Query}.
-
--spec map(request(FZD), fun((FZD) -> FZF)) -> request(FZF).
-map(Request, Transform) ->
- _pipe = erlang:element(4, Request),
- _pipe@1 = Transform(_pipe),
- set_body(Request, _pipe@1).
-
--spec path_segments(request(any())) -> list(binary()).
-path_segments(Request) ->
- _pipe = erlang:element(8, Request),
- gleam@uri:path_segments(_pipe).
-
--spec get_query(request(any())) -> {ok, list({binary(), binary()})} |
- {error, nil}.
-get_query(Request) ->
- case erlang:element(9, Request) of
- {some, Query_string} ->
- gleam@uri:parse_query(Query_string);
-
- none ->
- {ok, []}
- end.
-
--spec set_query(request(FZP), list({binary(), binary()})) -> request(FZP).
-set_query(Req, Query) ->
- Pair = fun(T) ->
- gleam@string_builder:from_strings(
- [erlang:element(1, T), <<"="/utf8>>, erlang:element(2, T)]
- )
- end,
- Query@1 = begin
- _pipe = Query,
- _pipe@1 = gleam@list:map(_pipe, Pair),
- _pipe@2 = gleam@list:intersperse(
- _pipe@1,
- gleam@string_builder:from_string(<<"&"/utf8>>)
- ),
- _pipe@3 = gleam@string_builder:concat(_pipe@2),
- _pipe@4 = gleam@string_builder:to_string(_pipe@3),
- {some, _pipe@4}
- end,
- erlang:setelement(9, Req, Query@1).
-
--spec set_method(request(FZT), gleam@http:method()) -> request(FZT).
-set_method(Req, Method) ->
- erlang:setelement(2, Req, Method).
-
--spec new() -> request(binary()).
-new() ->
- {request,
- get,
- [],
- <<""/utf8>>,
- https,
- <<"localhost"/utf8>>,
- none,
- <<""/utf8>>,
- none}.
-
--spec to(binary()) -> {ok, request(binary())} | {error, nil}.
-to(Url) ->
- _pipe = Url,
- _pipe@1 = gleam@uri:parse(_pipe),
- gleam@result:then(_pipe@1, fun from_uri/1).
-
--spec set_scheme(request(GAA), gleam@http:scheme()) -> request(GAA).
-set_scheme(Req, Scheme) ->
- erlang:setelement(5, Req, Scheme).
-
--spec set_host(request(GAD), binary()) -> request(GAD).
-set_host(Req, Host) ->
- erlang:setelement(6, Req, Host).
-
--spec set_port(request(GAG), integer()) -> request(GAG).
-set_port(Req, Port) ->
- erlang:setelement(7, Req, {some, Port}).
-
--spec set_path(request(GAJ), binary()) -> request(GAJ).
-set_path(Req, Path) ->
- erlang:setelement(8, Req, Path).
-
--spec set_cookie(request(GAM), binary(), binary()) -> request(GAM).
-set_cookie(Req, Name, Value) ->
- New_cookie_string = gleam@string:join([Name, Value], <<"="/utf8>>),
- {Cookies_string@2, Headers@1} = case gleam@list:key_pop(
- erlang:element(3, Req),
- <<"cookie"/utf8>>
- ) of
- {ok, {Cookies_string, Headers}} ->
- Cookies_string@1 = gleam@string:join(
- [Cookies_string, New_cookie_string],
- <<"; "/utf8>>
- ),
- {Cookies_string@1, Headers};
-
- {error, nil} ->
- {New_cookie_string, erlang:element(3, Req)}
- end,
- erlang:setelement(
- 3,
- Req,
- [{<<"cookie"/utf8>>, Cookies_string@2} | Headers@1]
- ).
-
--spec get_cookies(request(any())) -> list({binary(), binary()}).
-get_cookies(Req) ->
- {request, _, Headers, _, _, _, _, _, _} = Req,
- _pipe = Headers,
- _pipe@1 = gleam@list:filter_map(
- _pipe,
- fun(Header) ->
- {Name, Value} = Header,
- case Name of
- <<"cookie"/utf8>> ->
- {ok, gleam@http@cookie:parse(Value)};
-
- _ ->
- {error, nil}
- end
- end
- ),
- gleam@list:flatten(_pipe@1).
diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl
deleted file mode 100644
index b073c1d..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam@http@response.erl
+++ /dev/null
@@ -1,97 +0,0 @@
--module(gleam@http@response).
--compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-
--export([new/1, get_header/2, set_header/3, prepend_header/3, set_body/2, try_map/2, map/2, redirect/1, get_cookies/1, set_cookie/4, expire_cookie/3]).
--export_type([response/1]).
-
--type response(GFN) :: {response, integer(), list({binary(), binary()}), GFN}.
-
--spec new(integer()) -> response(binary()).
-new(Status) ->
- {response, Status, [], <<""/utf8>>}.
-
--spec get_header(response(any()), binary()) -> {ok, binary()} | {error, nil}.
-get_header(Response, Key) ->
- gleam@list:key_find(
- erlang:element(3, Response),
- gleam@string:lowercase(Key)
- ).
-
--spec set_header(response(GGC), binary(), binary()) -> response(GGC).
-set_header(Response, Key, Value) ->
- Headers = gleam@list:key_set(
- erlang:element(3, Response),
- gleam@string:lowercase(Key),
- Value
- ),
- erlang:setelement(3, Response, Headers).
-
--spec prepend_header(response(GGF), binary(), binary()) -> response(GGF).
-prepend_header(Response, Key, Value) ->
- Headers = [{gleam@string:lowercase(Key), Value} |
- erlang:element(3, Response)],
- erlang:setelement(3, Response, Headers).
-
--spec set_body(response(any()), GGK) -> response(GGK).
-set_body(Response, Body) ->
- {response, Status, Headers, _} = Response,
- {response, Status, Headers, Body}.
-
--spec try_map(response(GFO), fun((GFO) -> {ok, GFQ} | {error, GFR})) -> {ok,
- response(GFQ)} |
- {error, GFR}.
-try_map(Response, Transform) ->
- gleam@result:then(
- Transform(erlang:element(4, Response)),
- fun(Body) -> {ok, set_body(Response, Body)} end
- ).
-
--spec map(response(GGM), fun((GGM) -> GGO)) -> response(GGO).
-map(Response, Transform) ->
- _pipe = erlang:element(4, Response),
- _pipe@1 = Transform(_pipe),
- set_body(Response, _pipe@1).
-
--spec redirect(binary()) -> response(binary()).
-redirect(Uri) ->
- {response,
- 303,
- [{<<"location"/utf8>>, Uri}],
- gleam@string:append(<<"You are being redirected to "/utf8>>, Uri)}.
-
--spec get_cookies(response(any())) -> list({binary(), binary()}).
-get_cookies(Resp) ->
- {response, _, Headers, _} = Resp,
- _pipe = Headers,
- _pipe@1 = gleam@list:filter_map(
- _pipe,
- fun(Header) ->
- {Name, Value} = Header,
- case Name of
- <<"set-cookie"/utf8>> ->
- {ok, gleam@http@cookie:parse(Value)};
-
- _ ->
- {error, nil}
- end
- end
- ),
- gleam@list:flatten(_pipe@1).
-
--spec set_cookie(
- response(GGT),
- binary(),
- binary(),
- gleam@http@cookie:attributes()
-) -> response(GGT).
-set_cookie(Response, Name, Value, Attributes) ->
- prepend_header(
- Response,
- <<"set-cookie"/utf8>>,
- gleam@http@cookie:set_header(Name, Value, Attributes)
- ).
-
--spec expire_cookie(response(GGW), binary(), gleam@http@cookie:attributes()) -> response(GGW).
-expire_cookie(Response, Name, Attributes) ->
- Attrs = erlang:setelement(2, Attributes, {some, 0}),
- set_cookie(Response, Name, <<""/utf8>>, Attrs).
diff --git a/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl b/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl
deleted file mode 100644
index d07b31f..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam@http@service.erl
+++ /dev/null
@@ -1,82 +0,0 @@
--module(gleam@http@service).
--compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function]).
-
--export([map_response_body/2, prepend_response_header/3, method_override/1]).
-
--spec map_response_body(
- fun((gleam@http@request:request(GJL)) -> gleam@http@response:response(GJM)),
- fun((GJM) -> GJP)
-) -> fun((gleam@http@request:request(GJL)) -> gleam@http@response:response(GJP)).
-map_response_body(Service, Mapper) ->
- fun(Req) -> _pipe = Req,
- _pipe@1 = Service(_pipe),
- gleam@http@response:map(_pipe@1, Mapper) end.
-
--spec prepend_response_header(
- fun((gleam@http@request:request(GJS)) -> gleam@http@response:response(GJT)),
- binary(),
- binary()
-) -> fun((gleam@http@request:request(GJS)) -> gleam@http@response:response(GJT)).
-prepend_response_header(Service, Key, Value) ->
- fun(Req) -> _pipe = Req,
- _pipe@1 = Service(_pipe),
- gleam@http@response:prepend_header(_pipe@1, Key, Value) end.
-
--spec ensure_post(gleam@http@request:request(GJY)) -> {ok,
- gleam@http@request:request(GJY)} |
- {error, nil}.
-ensure_post(Req) ->
- case erlang:element(2, Req) of
- post ->
- {ok, Req};
-
- _ ->
- {error, nil}
- end.
-
--spec get_override_method(gleam@http@request:request(any())) -> {ok,
- gleam@http:method()} |
- {error, nil}.
-get_override_method(Request) ->
- gleam@result:then(
- gleam@http@request:get_query(Request),
- fun(Query_params) ->
- gleam@result:then(
- gleam@list:key_find(Query_params, <<"_method"/utf8>>),
- fun(Method) ->
- gleam@result:then(
- gleam@http:parse_method(Method),
- fun(Method@1) -> case Method@1 of
- put ->
- {ok, Method@1};
-
- patch ->
- {ok, Method@1};
-
- delete ->
- {ok, Method@1};
-
- _ ->
- {error, nil}
- end end
- )
- end
- )
- end
- ).
-
--spec method_override(
- fun((gleam@http@request:request(GKF)) -> gleam@http@response:response(GKG))
-) -> fun((gleam@http@request:request(GKF)) -> gleam@http@response:response(GKG)).
-method_override(Service) ->
- fun(Request) -> _pipe = Request,
- _pipe@1 = ensure_post(_pipe),
- _pipe@2 = gleam@result:then(_pipe@1, fun get_override_method/1),
- _pipe@3 = gleam@result:map(
- _pipe@2,
- fun(_capture) ->
- gleam@http@request:set_method(Request, _capture)
- end
- ),
- _pipe@4 = gleam@result:unwrap(_pipe@3, Request),
- Service(_pipe@4) end.
diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http.app.src b/aoc2023/build/packages/gleam_http/src/gleam_http.app.src
deleted file mode 100644
index c37ad54..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam_http.app.src
+++ /dev/null
@@ -1,12 +0,0 @@
-{application, gleam_http, [
- {vsn, "3.5.2"},
- {applications, [gleam_stdlib,
- gleeunit]},
- {description, "Types and functions for Gleam HTTP clients and servers"},
- {modules, [gleam@http,
- gleam@http@cookie,
- gleam@http@request,
- gleam@http@response,
- gleam@http@service]},
- {registered, []}
-]}.
diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl b/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl
deleted file mode 100644
index bb499bb..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam_http_native.erl
+++ /dev/null
@@ -1,88 +0,0 @@
--module(gleam_http_native).
--export([decode_method/1]).
-
-decode_method(Term) ->
- case Term of
- "connect" -> {ok, connect};
- "delete" -> {ok, delete};
- "get" -> {ok, get};
- "head" -> {ok, head};
- "options" -> {ok, options};
- "patch" -> {ok, patch};
- "post" -> {ok, post};
- "put" -> {ok, put};
- "trace" -> {ok, trace};
- "CONNECT" -> {ok, connect};
- "DELETE" -> {ok, delete};
- "GET" -> {ok, get};
- "HEAD" -> {ok, head};
- "OPTIONS" -> {ok, options};
- "PATCH" -> {ok, patch};
- "POST" -> {ok, post};
- "PUT" -> {ok, put};
- "TRACE" -> {ok, trace};
- "Connect" -> {ok, connect};
- "Delete" -> {ok, delete};
- "Get" -> {ok, get};
- "Head" -> {ok, head};
- "Options" -> {ok, options};
- "Patch" -> {ok, patch};
- "Post" -> {ok, post};
- "Put" -> {ok, put};
- "Trace" -> {ok, trace};
- 'connect' -> {ok, connect};
- 'delete' -> {ok, delete};
- 'get' -> {ok, get};
- 'head' -> {ok, head};
- 'options' -> {ok, options};
- 'patch' -> {ok, patch};
- 'post' -> {ok, post};
- 'put' -> {ok, put};
- 'trace' -> {ok, trace};
- 'CONNECT' -> {ok, connect};
- 'DELETE' -> {ok, delete};
- 'GET' -> {ok, get};
- 'HEAD' -> {ok, head};
- 'OPTIONS' -> {ok, options};
- 'PATCH' -> {ok, patch};
- 'POST' -> {ok, post};
- 'PUT' -> {ok, put};
- 'TRACE' -> {ok, trace};
- 'Connect' -> {ok, connect};
- 'Delete' -> {ok, delete};
- 'Get' -> {ok, get};
- 'Head' -> {ok, head};
- 'Options' -> {ok, options};
- 'Patch' -> {ok, patch};
- 'Post' -> {ok, post};
- 'Put' -> {ok, put};
- 'Trace' -> {ok, trace};
- <<"connect">> -> {ok, connect};
- <<"delete">> -> {ok, delete};
- <<"get">> -> {ok, get};
- <<"head">> -> {ok, head};
- <<"options">> -> {ok, options};
- <<"patch">> -> {ok, patch};
- <<"post">> -> {ok, post};
- <<"put">> -> {ok, put};
- <<"trace">> -> {ok, trace};
- <<"CONNECT">> -> {ok, connect};
- <<"DELETE">> -> {ok, delete};
- <<"GET">> -> {ok, get};
- <<"HEAD">> -> {ok, head};
- <<"OPTIONS">> -> {ok, options};
- <<"PATCH">> -> {ok, patch};
- <<"POST">> -> {ok, post};
- <<"PUT">> -> {ok, put};
- <<"TRACE">> -> {ok, trace};
- <<"Connect">> -> {ok, connect};
- <<"Delete">> -> {ok, delete};
- <<"Get">> -> {ok, get};
- <<"Head">> -> {ok, head};
- <<"Options">> -> {ok, options};
- <<"Patch">> -> {ok, patch};
- <<"Post">> -> {ok, post};
- <<"Put">> -> {ok, put};
- <<"Trace">> -> {ok, trace};
- _ -> {error, nil}
- end.
diff --git a/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs b/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs
deleted file mode 100644
index c871a8b..0000000
--- a/aoc2023/build/packages/gleam_http/src/gleam_http_native.mjs
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Ok, Error } from "./gleam.mjs";
-import {
- Get,
- Post,
- Head,
- Put,
- Delete,
- Trace,
- Connect,
- Options,
- Patch,
-} from "./gleam/http.mjs";
-
-export function decode_method(value) {
- try {
- switch (value.toLowerCase()) {
- case "get":
- return new Ok(new Get());
- case "post":
- return new Ok(new Post());
- case "head":
- return new Ok(new Head());
- case "put":
- return new Ok(new Put());
- case "delete":
- return new Ok(new Delete());
- case "trace":
- return new Ok(new Trace());
- case "connect":
- return new Ok(new Connect());
- case "options":
- return new Ok(new Options());
- case "patch":
- return new Ok(new Patch());
- }
- } catch {}
- return new Error(undefined);
-}