//// 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/bit_string import gleam/dynamic.{DecodeError, Dynamic} import gleam/int import gleam/list import gleam/option import gleam/regex import gleam/result import gleam/string import gleam/string_builder import gleam/uri /// 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_to_string("http") /// Ok(Http) /// /// > scheme_to_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), [])]) } } if erlang { external fn do_method_from_dynamic(Dynamic) -> Result(Method, nil) = "gleam_http_native" "decode_method" } if javascript { external fn do_method_from_dynamic(Dynamic) -> Result(Method, Nil) = "../gleam_http_native.mjs" "decode_method" } /// A HTTP header is a key-value pair. Header keys should be all lowercase /// characters. pub type Header = #(String, String)