Laravel AT Protocol Client (alpha & unstable)
3
fork

Configure Feed

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

Add dual-mode HTTP support for public and authenticated requests

+96 -7
+93 -4
src/Client/Client.php
··· 2 2 3 3 namespace SocialDept\AtpClient\Client; 4 4 5 + use BackedEnum; 6 + use Illuminate\Support\Facades\Http; 5 7 use SocialDept\AtpClient\AtpClient; 8 + use SocialDept\AtpClient\Exceptions\AtpResponseException; 6 9 use SocialDept\AtpClient\Http\DPoPClient; 7 10 use SocialDept\AtpClient\Http\HasHttp; 11 + use SocialDept\AtpClient\Http\Response; 8 12 use SocialDept\AtpClient\Session\Session; 9 13 use SocialDept\AtpClient\Session\SessionManager; 10 14 11 15 class Client 12 16 { 13 - use HasHttp; 17 + use HasHttp { 18 + call as authenticatedCall; 19 + postBlob as authenticatedPostBlob; 20 + } 14 21 15 22 /** 16 23 * The parent AtpClient instance we belong to 17 24 */ 18 25 protected AtpClient $atp; 19 26 27 + /** 28 + * Service URL for public mode 29 + */ 30 + protected ?string $serviceUrl; 31 + 20 32 public function __construct( 21 33 AtpClient $parent, 22 - SessionManager $sessions, 23 - string $did, 34 + ?SessionManager $sessions = null, 35 + ?string $did = null, 36 + ?string $serviceUrl = null, 24 37 ) { 25 38 $this->atp = $parent; 26 39 $this->sessions = $sessions; 27 40 $this->did = $did; 28 - $this->dpopClient = app(DPoPClient::class); 41 + $this->serviceUrl = $serviceUrl; 42 + 43 + if (! $this->isPublicMode()) { 44 + $this->dpopClient = app(DPoPClient::class); 45 + } 46 + } 47 + 48 + /** 49 + * Check if client is in public mode (no authentication). 50 + */ 51 + public function isPublicMode(): bool 52 + { 53 + return $this->sessions === null || $this->did === null; 29 54 } 30 55 31 56 /** ··· 34 59 public function session(): Session 35 60 { 36 61 return $this->sessions->session($this->did); 62 + } 63 + 64 + /** 65 + * Get the service URL. 66 + */ 67 + public function serviceUrl(): string 68 + { 69 + return $this->serviceUrl; 70 + } 71 + 72 + /** 73 + * Make XRPC call - routes to public or authenticated based on mode. 74 + */ 75 + protected function call( 76 + string|BackedEnum $endpoint, 77 + string $method, 78 + ?array $params = null, 79 + ?array $body = null 80 + ): Response { 81 + if ($this->isPublicMode()) { 82 + return $this->publicCall($endpoint, $method, $params, $body); 83 + } 84 + 85 + return $this->authenticatedCall($endpoint, $method, $params, $body); 86 + } 87 + 88 + /** 89 + * Make public XRPC call (no authentication). 90 + */ 91 + protected function publicCall( 92 + string|BackedEnum $endpoint, 93 + string $method, 94 + ?array $params = null, 95 + ?array $body = null 96 + ): Response { 97 + $endpoint = $endpoint instanceof BackedEnum ? $endpoint->value : $endpoint; 98 + $url = rtrim($this->serviceUrl, '/') . '/xrpc/' . $endpoint; 99 + $params = array_filter($params ?? [], fn ($v) => ! is_null($v)); 100 + 101 + $response = match ($method) { 102 + 'GET' => Http::get($url, $params), 103 + 'POST' => Http::post($url, $body ?? $params), 104 + 'DELETE' => Http::delete($url, $params), 105 + default => throw new \InvalidArgumentException("Unsupported method: {$method}"), 106 + }; 107 + 108 + if ($response->failed() || isset($response->json()['error'])) { 109 + throw AtpResponseException::fromResponse($response, $endpoint); 110 + } 111 + 112 + return new Response($response); 113 + } 114 + 115 + /** 116 + * Make POST request with raw binary body (for blob uploads). 117 + * Only works in authenticated mode. 118 + */ 119 + public function postBlob(string|BackedEnum $endpoint, string $data, string $mimeType): Response 120 + { 121 + if ($this->isPublicMode()) { 122 + throw new \RuntimeException('Blob uploads require authentication.'); 123 + } 124 + 125 + return $this->authenticatedPostBlob($endpoint, $data, $mimeType); 37 126 } 38 127 }
+3 -3
src/Http/HasHttp.php
··· 16 16 17 17 trait HasHttp 18 18 { 19 - protected SessionManager $sessions; 19 + protected ?SessionManager $sessions = null; 20 20 21 - protected string $did; 21 + protected ?string $did = null; 22 22 23 - protected DPoPClient $dpopClient; 23 + protected ?DPoPClient $dpopClient = null; 24 24 25 25 protected ?ScopeChecker $scopeChecker = null; 26 26