Current section

Files

Jump to
gleam_fetch src gleam fetch.gleam
Raw

src/gleam/fetch.gleam

import gleam/dynamic.{type Dynamic}
import gleam/fetch/form_data.{type FormData}
import gleam/http/request.{type Request}
import gleam/http/response.{type Response}
import gleam/javascript/promise.{type Promise}
/// Fetch errors can be due to a network error or a runtime error. A common
/// mistake is to try to consume the response body twice, or to try to read the
/// response body as JSON while it's not a valid JSON.
///
/// Take note that a 500 response is not considered as an error: it is a
/// successful request, which indicates the server triggers an error.
pub type FetchError {
/// A network error occured, maybe because user lost network connection,
/// because the network took to long to answer, or because the
/// server timed out.
NetworkError(String)
/// Fetch is unable to read body, for example when body as already been read
/// once.
UnableToReadBody
InvalidJsonBody
}
pub type FetchBody
/// Gleam equivalent of JavaScript [`Request`](https://developer.mozilla.org/docs/Web/API/Request).
pub type FetchRequest
/// Gleam equivalent of JavaScript [`Response`](https://developer.mozilla.org/docs/Web/API/Response).
pub type FetchResponse
/// Call directly `fetch` with a `Request`, and convert the result back to Gleam.
/// Let you get back a `FetchResponse` instead of the Gleam
/// `gleam/http/response.Response` data.
///
/// ```gleam
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> fetch.to_fetch_request
/// |> fetch.raw_send
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "raw_send")
pub fn raw_send(a: FetchRequest) -> Promise(Result(FetchResponse, FetchError))
/// Call `fetch` with a Gleam `Request(String)`, and convert the result back
/// to Gleam. Use it to send strings or JSON stringified.
///
/// If you're looking for something more low-level, take a look at
/// [`raw_send`](#raw_send).
///
/// ```gleam
/// let my_data = json.object([#("field", "value")])
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(json.to_string(my_data))
/// |> request.set_header("content-type", "application/json")
/// |> fetch.send
/// ```
pub fn send(
request: Request(String),
) -> Promise(Result(Response(FetchBody), FetchError)) {
request
|> to_fetch_request
|> raw_send
|> promise.try_await(fn(resp) {
promise.resolve(Ok(from_fetch_response(resp)))
})
}
/// Call `fetch` with a Gleam `Request(FormData)`, and convert the result back
/// to Gleam. Request will be sent as a `multipart/form-data`, and should be
/// decoded as-is on servers.
///
/// If you're looking for something more low-level, take a look at
/// [`raw_send`](#raw_send).
///
/// ```gleam
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body({
/// form_data.new()
/// |> form_data.append("key", "value")
/// })
/// |> fetch.send_form_data
/// ```
pub fn send_form_data(
request: Request(FormData),
) -> Promise(Result(Response(FetchBody), FetchError)) {
request
|> form_data_to_fetch_request
|> raw_send
|> promise.try_await(fn(resp) {
promise.resolve(Ok(from_fetch_response(resp)))
})
}
/// Call `fetch` with a Gleam `Request(FormData)`, and convert the result back
/// to Gleam. Binary will be sent as-is, and you probably want a proper
/// content-type added.
///
/// If you're looking for something more low-level, take a look at
/// [`raw_send`](#raw_send).
///
/// ```gleam
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(<<"data">>)
/// |> request.set_header("content-type", "application/octet-stream")
/// |> fetch.send_form_data
/// ```
pub fn send_bits(
request: Request(BitArray),
) -> Promise(Result(Response(FetchBody), FetchError)) {
request
|> bitarray_request_to_fetch_request
|> raw_send
|> promise.try_await(fn(resp) {
promise.resolve(Ok(from_fetch_response(resp)))
})
}
/// Convert a Gleam `Request(String)` to a JavaScript
/// [`Request`](https://developer.mozilla.org/docs/Web/API/Request), where
/// `body` is a string.
///
/// Can be used in conjuction with `raw_send`, or when you need to reuse your
/// `Request` in JavaScript FFI.
///
/// ```gleam
/// let request =
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// fetch.to_fetch_request(request)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "to_fetch_request")
pub fn to_fetch_request(a: Request(String)) -> FetchRequest
/// Convert a Gleam `Request(FormData)` to a JavaScript
/// [`Request`](https://developer.mozilla.org/docs/Web/API/Request), where
/// `body` is a JavaScript `FormData` object.
///
/// Can be used in conjuction with `raw_send`, or when you need to reuse your
/// `Request` in JavaScript FFI.
///
/// ```gleam
/// let request =
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body({
/// form_data.new()
/// |> form_data.append("key", "value")
/// })
/// fetch.form_data_to_fetch_request(request)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "form_data_to_fetch_request")
pub fn form_data_to_fetch_request(a: Request(FormData)) -> FetchRequest
/// Convert a Gleam `Request(BitArray)` to a JavaScript
/// [`Request`](https://developer.mozilla.org/docs/Web/API/Request), where
/// `body` is a JavaScript `UInt8Array` object.
///
/// Can be used in conjuction with `raw_send`, or when you need to reuse your
/// `Request` in JavaScript FFI.
///
/// ```gleam
/// let request =
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(<<"data">>)
/// fetch.bitarray_request_to_fetch_request(request)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "bitarray_request_to_fetch_request")
pub fn bitarray_request_to_fetch_request(a: Request(BitArray)) -> FetchRequest
/// Convert a JavaScript [`Response`](https://developer.mozilla.org/docs/Web/API/Response)
/// into a Gleam `Response(FetchBody)`. Can be used with the result of
/// `raw_send`, or with some data received through the FFI.
///
/// ```gleam
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> fetch.to_fetch_request
/// |> fetch.raw_send
/// |> promise.map_try(fetch.from_fetch_response)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "from_fetch_response")
pub fn from_fetch_response(a: FetchResponse) -> Response(FetchBody)
/// Read a response body as a BitArray. Returns an error when the body is not a
/// valid BitArray. Because `fetch.send` returns a `Promise` and every
/// functions to read response body are also asynchronous, take care to properly
/// use `gleam/javascript/promise` to combine them.
///
/// ```gleam
/// let my_data = json.object([#("field", "value")])
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(json.to_string(my_data))
/// |> request.set_header("content-type", "application/json")
/// |> fetch.send
/// |> promise.try_await(fetch.read_bytes_body)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "read_bytes_body")
pub fn read_bytes_body(
a: Response(FetchBody),
) -> Promise(Result(Response(BitArray), FetchError))
/// Read a response body as a String. Returns an error when the body is not a
/// valid String. Because `fetch.send` returns a `Promise` and every
/// functions to read response body are also asynchronous, take care to properly
/// use `gleam/javascript/promise` to combine them.
///
/// ```gleam
/// let my_data = json.object([#("field", "value")])
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(json.to_string(my_data))
/// |> request.set_header("content-type", "application/json")
/// |> fetch.send
/// |> promise.try_await(fetch.read_text_body)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "read_text_body")
pub fn read_text_body(
a: Response(FetchBody),
) -> Promise(Result(Response(String), FetchError))
/// Read a response body as a JSON. Returns an error when the body is not a
/// valid String. Because `fetch.send` returns a `Promise` and every
/// functions to read response body are also asynchronous, take care to properly
/// use `gleam/javascript/promise` to combine them.
///
/// Once read, you probably want to use
/// [`gleam/dynamic/decode`](https://hexdocs.pm/gleam_stdlib/gleam/dynamic/decode.html)
/// to decode its content in proper Gleam data.
///
/// ```gleam
/// let my_data = json.object([#("field", "value")])
/// request.new()
/// |> request.set_host("example.com")
/// |> request.set_path("/example")
/// |> request.set_body(json.to_string(my_data))
/// |> request.set_header("content-type", "application/json")
/// |> fetch.send
/// |> promise.try_await(fetch.read_json_body)
/// ```
@external(javascript, "../gleam_fetch_ffi.mjs", "read_json_body")
pub fn read_json_body(
a: Response(FetchBody),
) -> Promise(Result(Response(Dynamic), FetchError))