138 - Add multipart upload support to LemmyRequest
This commit is contained in:
parent
0163fa53b4
commit
6ea3f922da
2 changed files with 79 additions and 0 deletions
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
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 $token;
|
||||
|
|
@ -83,6 +86,27 @@ public function post(string $endpoint, array $data = []): Response
|
|||
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
|
||||
{
|
||||
$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
|
||||
{
|
||||
$reflection = new \ReflectionClass($object);
|
||||
|
|
|
|||
Loading…
Reference in a new issue