Laravel AT Protocol Client (alpha & unstable)
at main 3.5 kB view raw
1<?php 2 3namespace SocialDept\AtpClient\Client; 4 5use BackedEnum; 6use Illuminate\Support\Facades\Http; 7use SocialDept\AtpClient\AtpClient; 8use SocialDept\AtpClient\Exceptions\AtpResponseException; 9use SocialDept\AtpClient\Http\DPoPClient; 10use SocialDept\AtpClient\Http\HasHttp; 11use SocialDept\AtpClient\Http\Response; 12use SocialDept\AtpClient\Session\Session; 13use SocialDept\AtpClient\Session\SessionManager; 14 15class Client 16{ 17 use HasHttp { 18 call as authenticatedCall; 19 postBlob as authenticatedPostBlob; 20 } 21 22 /** 23 * The parent AtpClient instance we belong to 24 */ 25 protected AtpClient $atp; 26 27 /** 28 * Service URL for public mode 29 */ 30 protected ?string $serviceUrl; 31 32 public function __construct( 33 AtpClient $parent, 34 ?SessionManager $sessions = null, 35 ?string $did = null, 36 ?string $serviceUrl = null, 37 ) { 38 $this->atp = $parent; 39 $this->sessions = $sessions; 40 $this->did = $did; 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; 54 } 55 56 /** 57 * Get the current session. 58 */ 59 public function session(): Session 60 { 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); 126 } 127}