An Elixir toolkit for the AT Protocol. hexdocs.pm/atex
elixir bluesky atproto decentralization
25
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: unauthed xrpc client

+57 -5
+10 -4
CHANGELOG.md
··· 6 6 and this project adheres to 7 7 [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 8 8 9 - <!--## [Unreleased]--> 9 + ## [Unreleased] 10 + 11 + ### Added 12 + 13 + - `Atex.XRPC.UnauthedClient` module for running unauthenticated XRPC fetches on 14 + public APIs or PDSes. 10 15 11 16 ## [0.8.0] - 2026-03-29 12 17 ··· 48 53 - `Atex.XRPC.Router` module with `query/3` and `procedure/3` macros for easily 49 54 building XRPC server routes inside a `Plug.Router`, with built-in service auth 50 55 validation and validation if passed the name of a module using `deflexicon`. 51 - - `deflexicon` now emits `content_type/0` functions (on `Input` submodules for typed JSON bodies, 52 - otherwise on the root module) for procedures. 53 - - `Atex.XRPC.ServiceAuthClient` module for making requests to other atproto services using a service auth token. 56 + - `deflexicon` now emits `content_type/0` functions (on `Input` submodules for 57 + typed JSON bodies, otherwise on the root module) for procedures. 58 + - `Atex.XRPC.ServiceAuthClient` module for making requests to other atproto 59 + services using a service auth token. 54 60 55 61 ### Fixed 56 62
-1
lib/atex/xrpc/service_auth_client.ex
··· 8 8 ## Usage 9 9 10 10 client = Atex.XRPC.ServiceAuthClient.new("<jwt>") 11 - 12 11 {:ok, response, _} = Atex.XRPC.get(client, "com.example.authenticatedXRPC") 13 12 """ 14 13
+47
lib/atex/xrpc/unauthed_client.ex
··· 1 + defmodule Atex.XRPC.UnauthedClient do 2 + @moduledoc """ 3 + An XRPC client that doesn't perform any authentication to a service. 4 + Can be used for public APIs like `public.api.bsky.app`, or performing 5 + public reads from PDSes. 6 + 7 + ## Usage 8 + 9 + client = Atex.XRPC.UnauthedClient.new("https://public.api.bsky.app") 10 + {:ok, response, client} = Atex.XRPC.get(client, "app.bsky.actor.getProfile", params: [actor: "ovyerus.com"]) 11 + """ 12 + 13 + use TypedStruct 14 + @behaviour Atex.XRPC.Client 15 + 16 + typedstruct do 17 + field :endpoint, String.t(), enforce: true 18 + end 19 + 20 + @doc """ 21 + Create a new `Atex.XRPC.UnauthedClient`. 22 + """ 23 + @spec new(String.t()) :: t() 24 + def new(endpoint) when is_binary(endpoint), do: %__MODULE__{endpoint: endpoint} 25 + 26 + @impl true 27 + def get(%__MODULE__{endpoint: endpoint} = client, resource, opts \\ []) do 28 + (opts ++ [method: :get, url: Atex.XRPC.url(endpoint, resource)]) 29 + |> Req.new() 30 + |> Req.request() 31 + |> case do 32 + {:ok, response} -> {:ok, response, client} 33 + {:error, reason} -> {:error, reason, client} 34 + end 35 + end 36 + 37 + @impl true 38 + def post(%__MODULE__{endpoint: endpoint} = client, resource, opts \\ []) do 39 + (opts ++ [method: :post, url: Atex.XRPC.url(endpoint, resource)]) 40 + |> Req.new() 41 + |> Req.request() 42 + |> case do 43 + {:ok, response} -> {:ok, response, client} 44 + {:error, reason} -> {:error, reason, client} 45 + end 46 + end 47 + end