Packages

Gleam library for interacting with Automatic Certificate Management Environment (ACME) servers like Let's Encrypt

Retired package: Release invalid

Current section

Files

Jump to
acumen src acumen@fetch_renewal_info.erl
Raw

src/acumen@fetch_renewal_info.erl

-module(acumen@fetch_renewal_info).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/acumen/fetch_renewal_info.gleam").
-export([build/2, response/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Fetch renewal information for a certificate (RFC 9773).\n"
"\n"
" Queries the ACME server for a suggested renewal window for a specific\n"
" certificate. This uses an unauthenticated GET request (no JWS signing\n"
" needed), so it does not require `acumen.execute` — just build, send,\n"
" and parse the response directly.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import acumen\n"
" import acumen/fetch_renewal_info\n"
" import acumen/renewal_info\n"
" import gleam/httpc\n"
" import kryptos/x509/certificate\n"
"\n"
" // Parse the certificate and build the identifier\n"
" let assert Ok(certs) = certificate.from_pem(pem)\n"
" let assert [cert, ..] = certs\n"
" let assert Ok(cert_id) = renewal_info.cert_id_from_certificate(cert)\n"
"\n"
" // Fetch renewal information\n"
" let assert Ok(req) = fetch_renewal_info.build(directory, cert_id)\n"
" let assert Ok(resp) = httpc.send(req)\n"
" let assert Ok(info) = fetch_renewal_info.response(resp)\n"
"\n"
" // Check the suggested renewal window\n"
" let start = info.suggested_window.start\n"
" let end = info.suggested_window.end\n"
"\n"
" // Check polling interval\n"
" let retry = acumen.retry_after(resp)\n"
" ```\n"
).
-file("src/acumen/fetch_renewal_info.gleam", 51).
?DOC(
" Builds an HTTP GET request to fetch renewal information for a certificate.\n"
"\n"
" Targets `{renewalInfo_url}/{cert_id}`. Build the `cert_id` with\n"
" `renewal_info.cert_id` or `renewal_info.cert_id_from_certificate`.\n"
).
-spec build(acumen:directory(), binary()) -> {ok,
gleam@http@request:request(binary())} |
{error, acumen:acme_error()}.
build(Directory, Cert_id) ->
case erlang:element(8, Directory) of
none ->
{error,
{invalid_request,
<<"directory does not include renewalInfo endpoint"/utf8>>}};
{some, Base_uri} ->
Base_path = case gleam_stdlib:string_ends_with(
erlang:element(6, Base_uri),
<<"/"/utf8>>
) of
true ->
erlang:element(6, Base_uri);
false ->
<<(erlang:element(6, Base_uri))/binary, "/"/utf8>>
end,
_pipe = {uri,
erlang:element(2, Base_uri),
erlang:element(3, Base_uri),
erlang:element(4, Base_uri),
erlang:element(5, Base_uri),
<<Base_path/binary, Cert_id/binary>>,
erlang:element(7, Base_uri),
erlang:element(8, Base_uri)},
_pipe@1 = gleam@http@request:from_uri(_pipe),
_pipe@4 = gleam@result:map(_pipe@1, fun(Req) -> _pipe@2 = Req,
_pipe@3 = gleam@http@request:set_header(
_pipe@2,
<<"user-agent"/utf8>>,
<<"acumen/"/utf8, (<<"1.0.0"/utf8>>)/binary>>
),
gleam@http@request:set_header(
_pipe@3,
<<"accept-language"/utf8>>,
<<"en"/utf8>>
) end),
gleam@result:replace_error(
_pipe@4,
{invalid_request, <<"invalid renewalInfo URI"/utf8>>}
)
end.
-file("src/acumen/fetch_renewal_info.gleam", 79).
?DOC(" Parses a renewal information response.\n").
-spec response(gleam@http@response:response(binary())) -> {ok,
acumen@renewal_info:renewal_info()} |
{error, acumen:acme_error()}.
response(Resp) ->
case erlang:element(2, Resp) of
200 ->
_pipe = gleam@json:parse(
erlang:element(4, Resp),
acumen@renewal_info:decoder()
),
gleam@result:map_error(
_pipe,
fun(Error) ->
{json_parse_error,
acumen@internal@utils:json_parse_error_message(
<<"renewalInfo"/utf8>>,
Error
)}
end
);
_ ->
{error, acumen:parse_acme_error(Resp)}
end.