Release v1.4.0 #146
2 changed files with 79 additions and 0 deletions
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
class LemmyRequest
|
class LemmyRequest
|
||||||
{
|
{
|
||||||
|
// Uploads carry an image payload; the 30s used for JSON calls is not enough.
|
||||||
|
private const UPLOAD_TIMEOUT_SECONDS = 60;
|
||||||
|
|
||||||
private string $instance;
|
private string $instance;
|
||||||
|
|
||||||
private ?string $token;
|
private ?string $token;
|
||||||
|
|
@ -83,6 +86,27 @@ public function post(string $endpoint, array $data = []): Response
|
||||||
return $request->post($url, $data);
|
return $request->post($url, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pict-rs is mounted outside the /api/v3 prefix, so this takes a root-relative path.
|
||||||
|
*
|
||||||
|
* @param string $path Root-relative, e.g. 'pictrs/image'
|
||||||
|
* @param string $name Multipart field name, e.g. 'images[]'
|
||||||
|
* @param string $contents Raw file bytes
|
||||||
|
* @param string $filename Filename sent with the part
|
||||||
|
*/
|
||||||
|
public function postMultipart(string $path, string $name, string $contents, string $filename): Response
|
||||||
|
{
|
||||||
|
$url = sprintf('%s://%s/%s', $this->scheme, $this->instance, ltrim($path, '/'));
|
||||||
|
|
||||||
|
$request = Http::timeout(self::UPLOAD_TIMEOUT_SECONDS);
|
||||||
|
|
||||||
|
if ($this->token) {
|
||||||
|
$request = $request->withToken($this->token);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $request->attach($name, $contents, $filename)->post($url);
|
||||||
|
}
|
||||||
|
|
||||||
public function withToken(string $token): self
|
public function withToken(string $token): self
|
||||||
{
|
{
|
||||||
$this->token = $token;
|
$this->token = $token;
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,61 @@ public function test_chaining_methods(): void
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_post_multipart_targets_a_root_relative_path(): void
|
||||||
|
{
|
||||||
|
Http::fake(['*' => Http::response(['files' => []])]);
|
||||||
|
|
||||||
|
$request = new LemmyRequest('lemmy.world', 'test-token');
|
||||||
|
$response = $request->postMultipart('pictrs/image', 'images[]', 'binary-data', 'thumb.jpg');
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Response::class, $response);
|
||||||
|
|
||||||
|
Http::assertSent(function ($httpRequest) {
|
||||||
|
return $httpRequest->url() === 'https://lemmy.world/pictrs/image'
|
||||||
|
&& $httpRequest->header('Authorization')[0] === 'Bearer test-token';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_post_multipart_does_not_use_the_api_prefix(): void
|
||||||
|
{
|
||||||
|
Http::fake(['*' => Http::response(['files' => []])]);
|
||||||
|
|
||||||
|
(new LemmyRequest('lemmy.world'))->postMultipart('/pictrs/image', 'images[]', 'data', 'thumb.jpg');
|
||||||
|
|
||||||
|
Http::assertSent(fn ($httpRequest) => ! str_contains($httpRequest->url(), '/api/v3/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_post_multipart_sends_the_file_as_multipart_data(): void
|
||||||
|
{
|
||||||
|
Http::fake(['*' => Http::response(['files' => []])]);
|
||||||
|
|
||||||
|
(new LemmyRequest('lemmy.world'))->postMultipart('pictrs/image', 'images[]', 'binary-data', 'thumb.jpg');
|
||||||
|
|
||||||
|
Http::assertSent(function ($httpRequest) {
|
||||||
|
return str_contains($httpRequest->header('Content-Type')[0], 'multipart/form-data')
|
||||||
|
&& str_contains($httpRequest->body(), 'binary-data')
|
||||||
|
&& str_contains($httpRequest->body(), 'thumb.jpg');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_post_multipart_omits_authorization_without_a_token(): void
|
||||||
|
{
|
||||||
|
Http::fake(['*' => Http::response(['files' => []])]);
|
||||||
|
|
||||||
|
(new LemmyRequest('lemmy.world'))->postMultipart('pictrs/image', 'images[]', 'data', 'thumb.jpg');
|
||||||
|
|
||||||
|
Http::assertSent(fn ($httpRequest) => ! $httpRequest->hasHeader('Authorization'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_post_multipart_respects_the_scheme(): void
|
||||||
|
{
|
||||||
|
Http::fake(['*' => Http::response(['files' => []])]);
|
||||||
|
|
||||||
|
(new LemmyRequest('http://lemmy.world'))->postMultipart('pictrs/image', 'images[]', 'data', 'thumb.jpg');
|
||||||
|
|
||||||
|
Http::assertSent(fn ($httpRequest) => $httpRequest->url() === 'http://lemmy.world/pictrs/image');
|
||||||
|
}
|
||||||
|
|
||||||
private function getPrivateProperty(object $object, string $property): mixed
|
private function getPrivateProperty(object $object, string $property): mixed
|
||||||
{
|
{
|
||||||
$reflection = new \ReflectionClass($object);
|
$reflection = new \ReflectionClass($object);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue