Unify HTTP metadata handling

This commit is contained in:
2026-03-18 18:00:07 +01:00
parent c30449b318
commit 9014912e9d
11 changed files with 166 additions and 6 deletions

48
lib/parrhesia/http.ex Normal file
View File

@@ -0,0 +1,48 @@
defmodule Parrhesia.HTTP do
@moduledoc false
alias Parrhesia.Metadata
@default_headers [{"user-agent", Metadata.user_agent()}]
@spec default_headers() :: [{String.t(), String.t()}]
def default_headers, do: @default_headers
@spec get(Keyword.t()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
def get(options) when is_list(options) do
Req.get(put_default_headers(options))
end
@spec post(Keyword.t()) :: {:ok, Req.Response.t()} | {:error, Exception.t()}
def post(options) when is_list(options) do
Req.post(put_default_headers(options))
end
@spec put_default_headers(Keyword.t()) :: Keyword.t()
def put_default_headers(options) when is_list(options) do
Keyword.update(options, :headers, @default_headers, &merge_headers(&1, @default_headers))
end
defp merge_headers(headers, defaults) do
existing_names =
headers
|> List.wrap()
|> Enum.reduce(MapSet.new(), fn
{name, _value}, acc -> MapSet.put(acc, normalize_header_name(name))
_other, acc -> acc
end)
headers ++
Enum.reject(defaults, fn {name, _value} ->
MapSet.member?(existing_names, normalize_header_name(name))
end)
end
defp normalize_header_name(name) when is_atom(name) do
name
|> Atom.to_string()
|> String.downcase()
end
defp normalize_header_name(name) when is_binary(name), do: String.downcase(name)
end

29
lib/parrhesia/metadata.ex Normal file
View File

@@ -0,0 +1,29 @@
defmodule Parrhesia.Metadata do
@moduledoc false
@metadata Application.compile_env(:parrhesia, :metadata, [])
@name Keyword.get(@metadata, :name, "Parrhesia")
@version Keyword.get(@metadata, :version, "0.0.0")
@hide_version? Keyword.get(@metadata, :hide_version?, true)
@spec name() :: String.t()
def name, do: @name
@spec version() :: String.t()
def version, do: @version
@spec hide_version?() :: boolean()
def hide_version?, do: @hide_version?
@spec name_and_version() :: String.t()
def name_and_version, do: "#{@name}/#{@version}"
@spec user_agent() :: String.t()
def user_agent do
if hide_version?() do
name()
else
name_and_version()
end
end
end

View File

@@ -1,6 +1,7 @@
defmodule Parrhesia.NIP66.Probe do
@moduledoc false
alias Parrhesia.HTTP
alias Parrhesia.Sync.Transport.WebSockexClient
@type result :: %{
@@ -145,7 +146,7 @@ defmodule Parrhesia.NIP66.Probe do
defp fetch_nip11(relay_url, timeout_ms) do
started_at = System.monotonic_time()
case Req.get(
case HTTP.get(
url: relay_info_url(relay_url),
headers: [{"accept", "application/nostr+json"}],
decode_body: false,

View File

@@ -1,6 +1,7 @@
defmodule Parrhesia.Sync.RelayInfoClient do
@moduledoc false
alias Parrhesia.HTTP
alias Parrhesia.Sync.TLS
@spec verify_remote_identity(map(), keyword()) :: :ok | {:error, term()}
@@ -18,7 +19,7 @@ defmodule Parrhesia.Sync.RelayInfoClient do
end
defp default_request(url, opts) do
case Req.get(
case HTTP.get(
url: url,
headers: [{"accept", "application/nostr+json"}],
decode_body: false,

View File

@@ -4,21 +4,27 @@ defmodule Parrhesia.Web.RelayInfo do
"""
alias Parrhesia.API.Identity
alias Parrhesia.Metadata
alias Parrhesia.NIP43
alias Parrhesia.Web.Listener
@spec document(Listener.t()) :: map()
def document(listener) do
%{
"name" => "Parrhesia",
document = %{
"name" => Metadata.name(),
"description" => "Nostr/Marmot relay",
"pubkey" => relay_pubkey(),
"self" => relay_pubkey(),
"supported_nips" => supported_nips(),
"software" => "https://git.teralink.net/self/parrhesia",
"version" => Application.spec(:parrhesia, :vsn) |> to_string(),
"limitation" => limitations(listener)
}
if Metadata.hide_version?() do
document
else
Map.put(document, "version", Metadata.version())
end
end
defp supported_nips do