Current section

Files

Jump to
finch_gleam src finch.gleam
Raw

src/finch.gleam

//// Finch API wrapper module.
////
//// See the [Finch documentation](https://hexdocs.pm/finch) for additional
//// information about the functions.
import gleam/result
import gleam
import gleam/uri
import gleam/erlang/atom.{type Atom}
import gleam/http
import gleam/http/request as gleam_request
import gleam/http/response as gleam_response
import finch/headers.{type Headers}
import finch/stream.{type StreamFun}
import finch/otp.{type InstanceOptions, type OnStart}
// Finch's HTTP method type
type Method {
Head
Get
Put
Post
Patch
Delete
Options
}
pub type RequestOption {
PoolTimeout(ms: Int)
RequestTimeout(ms: Int)
}
pub type RequestOptions =
List(RequestOption)
/// Finch request, use `build/2` to create one from a Gleam request.
pub type Request
type Response
/// Exception returned by Finch in case of request errors.
pub type Exception
/// Build a Finch request that can be run with `request/2` or `stream/5`.
///
/// Note, the HTTP methods CONNECT, TRACE, and `Other(String)` are not
/// supported, and will be converted to GET.
pub fn build(
req: gleam_request.Request(String),
opts: RequestOptions,
) -> Request {
let url_str =
req
|> gleam_request.to_uri()
|> uri.to_string()
build_ext(
gleam_method_to_finch_method(req.method),
url_str,
req.headers,
req.body,
opts,
)
}
@external(erlang, "Elixir.Finch", "build")
fn build_ext(
method method: Method,
url url: String,
headers headers: Headers,
body body: String,
opts opts: RequestOptions,
) -> Request
/// Send a request using the Finch instance with the given name.
pub fn request(
req: Request,
name: Atom,
) -> Result(gleam_response.Response(String), Exception) {
use resp <- result.then(do_request(req, name))
gleam.Ok(gleam_response.Response(
body: response_body(resp),
headers: response_headers(resp),
status: response_status(resp),
))
}
@external(erlang, "Elixir.Finch", "request")
fn do_request(req req: Request, name name: Atom) -> Result(Response, Exception)
/// Stream a request using the Finch instance with the given name.
@external(erlang, "Elixir.Finch", "stream")
pub fn stream(
req req: Request,
name name: Atom,
acc acc: a,
fun fun: StreamFun(a),
opts opts: RequestOptions,
) -> Result(a, Exception)
/// Start a new Finch instance with the given options.
@external(erlang, "Elixir.Finch", "start_link")
pub fn start_link(opts opts: InstanceOptions) -> OnStart
fn response_body(resp: Response) -> String {
get_response_body(resp, Body)
}
fn response_headers(resp: Response) -> Headers {
get_response_headers(resp, Headers)
}
fn response_status(resp: Response) -> Int {
get_response_status(resp, Status)
}
fn gleam_method_to_finch_method(method: http.Method) -> Method {
case method {
http.Get -> Get
http.Head -> Head
http.Post -> Post
http.Put -> Put
http.Patch -> Patch
http.Delete -> Delete
http.Options -> Options
_other -> Get
}
}
type ResponseBodyKey {
Body
}
type ResponseHeadersKey {
Headers
}
type ResponseStatusKey {
Status
}
@external(erlang, "Elixir.Map", "fetch!")
fn get_response_body(resp resp: Response, key key: ResponseBodyKey) -> String
@external(erlang, "Elixir.Map", "fetch!")
fn get_response_status(resp resp: Response, key key: ResponseStatusKey) -> Int
@external(erlang, "Elixir.Map", "fetch!")
fn get_response_headers(
resp resp: Response,
key key: ResponseHeadersKey,
) -> Headers