Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
with:
php-version: ${{ matrix.php-version }}
extensions: curl
extensions: curl, swoole
coverage: none

- name: Install dependencies
uses: ramsey/composer-install@v3
uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0

- name: Audit dependencies
run: composer audit
Expand Down
65 changes: 52 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ Use `ext-curl` for the cURL adapter and `ext-swoole` for the Swoole coroutine ad

use Utopia\Client;
use Utopia\Client\Adapter\Curl\Client as CurlAdapter;
use Utopia\Psr7\Method;
use Utopia\Psr7\Request;

require __DIR__ . '/vendor/autoload.php';

$client = new Client(new CurlAdapter());
$requestFactory = new Request\Factory();

$request = $requestFactory->json('POST', 'https://example.com/users', [
$request = $requestFactory->json(Method::POST, 'https://example.com/users', [
'name' => 'Ada',
]);

Expand All @@ -56,11 +57,14 @@ Client defaults are immutable. Each `with*()` method returns a configured clone.
```php
<?php

use Utopia\Psr7\Header;
use Utopia\Psr7\ContentType;

$client = $client
->withBaseUri('https://api.example.com/v1')
->withHeaders([
'Accept' => 'application/json',
'User-Agent' => 'Acme API Client',
Header::ACCEPT => ContentType::JSON,
Header::USER_AGENT => 'Acme API Client',
])
->withBearerAuth('token');
```
Expand All @@ -70,9 +74,13 @@ Configured headers are defaults. If a request already has the same header, the r
```php
<?php

use Utopia\Psr7\ContentType;
use Utopia\Psr7\Header;
use Utopia\Psr7\Method;

$request = $requestFactory
->createRequest('GET', 'users')
->withHeader('Accept', 'application/xml');
->createRequest(Method::GET, 'users')
->withHeader(Header::ACCEPT, ContentType::XML);
```

Authentication helpers set the default `Authorization` header:
Expand All @@ -92,25 +100,26 @@ $client = $client->withBearerAuth('token');
<?php

use Utopia\Psr7\Request\Multipart\Part;
use Utopia\Psr7\Method;
use Utopia\Psr7\Request;

$requestFactory = new Request\Factory();

$json = $requestFactory->json('POST', 'https://api.example.com/users', [
$json = $requestFactory->json(Method::POST, 'https://api.example.com/users', [
'name' => 'Ada',
]);

$form = $requestFactory->form('POST', 'https://api.example.com/sessions', [
$form = $requestFactory->form(Method::POST, 'https://api.example.com/sessions', [
'email' => 'ada@example.com',
'password' => 'secret',
]);

$query = $requestFactory->query('GET', 'https://api.example.com/users?active=1', [
$query = $requestFactory->query(Method::GET, 'https://api.example.com/users?active=1', [
'page' => 2,
'search' => 'Ada Lovelace',
]);

$upload = $requestFactory->multipart('POST', 'https://api.example.com/uploads', [
$upload = $requestFactory->multipart(Method::POST, 'https://api.example.com/uploads', [
'name' => 'Ada',
'avatar' => Part::file('avatar', '/tmp/avatar.png', 'avatar.png', 'image/png'),
]);
Expand All @@ -121,11 +130,15 @@ Header overrides are explicit:
```php
<?php

$request = $requestFactory->json('PATCH', 'https://api.example.com/users/1', [
use Utopia\Psr7\ContentType;
use Utopia\Psr7\Header;
use Utopia\Psr7\Method;

$request = $requestFactory->json(Method::PATCH, 'https://api.example.com/users/1', [
'name' => 'Ada',
], [
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/merge-patch+json',
Header::ACCEPT => 'application/vnd.api+json',
Header::CONTENT_TYPE => ContentType::MERGE_PATCH_JSON,
]);
```

Expand Down Expand Up @@ -191,6 +204,7 @@ The Swoole adapter must run inside a coroutine.
use Swoole\Coroutine;
use Utopia\Client;
use Utopia\Client\Adapter\SwooleCoroutine\Client as SwooleAdapter;
use Utopia\Psr7\Method;
use Utopia\Psr7\Request;

require __DIR__ . '/vendor/autoload.php';
Expand All @@ -206,7 +220,7 @@ Coroutine\run(static function (): void {
);

$response = $client->sendRequest(
$requestFactory->query('GET', 'https://example.com', [
$requestFactory->query(Method::GET, 'https://example.com', [
'ping' => '1',
]),
);
Expand All @@ -225,9 +239,34 @@ Both adapters throw PSR-18 exceptions.
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\NetworkExceptionInterface;
use Psr\Http\Client\RequestExceptionInterface;
use Utopia\Client\Exception\AdapterPreconditionException;
use Utopia\Client\Exception\ConnectionException;
use Utopia\Client\Exception\DnsException;
use Utopia\Client\Exception\InvalidResponseException;
use Utopia\Client\Exception\InvalidUriException;
use Utopia\Client\Exception\ProtocolException;
use Utopia\Client\Exception\ProxyException;
use Utopia\Client\Exception\TlsException;
use Utopia\Client\Exception\TimeoutException;

try {
$response = $client->sendRequest($request);
} catch (TimeoutException $error) {
// Transport timeout.
} catch (DnsException $error) {
// DNS resolution failure.
} catch (TlsException $error) {
// TLS handshake or certificate failure.
} catch (ProxyException $error) {
// Proxy transport failure.
} catch (ProtocolException $error) {
// HTTP protocol transport failure.
} catch (ConnectionException $error) {
// Connection refused, reset, unreachable, or broken.
} catch (InvalidResponseException $error) {
// Malformed or invalid HTTP response.
} catch (InvalidUriException | AdapterPreconditionException $error) {
// Request or runtime precondition failure.
} catch (NetworkExceptionInterface $error) {
// DNS, connection, timeout, or transport failure.
} catch (RequestExceptionInterface $error) {
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^10.5 || ^11.0 || ^12.0",
"rector/rector": "^2.4",
"swoole/ide-helper": "^5.1"
"swoole/ide-helper": "^6.0"
},
"config": {
"platform": {
Expand Down
14 changes: 7 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
use Utopia\Client\Adapter;
use Utopia\Psr7\Header;
use Utopia\Psr7\Uri;

final class Client implements ClientInterface
Expand Down Expand Up @@ -76,14 +77,14 @@ public function withBaseUri(UriInterface|string $uri): self
public function withBasicAuth(string $username, string $password): self
{
return $this->withHeaders([
'Authorization' => 'Basic ' . base64_encode($username . ':' . $password),
Header::AUTHORIZATION => 'Basic ' . base64_encode($username . ':' . $password),
]);
}

public function withBearerAuth(string $token): self
{
return $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
Header::AUTHORIZATION => 'Bearer ' . $token,
]);
}

Expand Down
Loading