From c78d8a183d4e84a39867790735ad1d58a40e8766 Mon Sep 17 00:00:00 2001 From: nabim777 Date: Tue, 24 Dec 2024 16:21:39 +0545 Subject: [PATCH] check the location header Signed-off-by: nabim777 --- .../TestHelpers/TusClientWrapper.php | 294 ++++++++---------- .../acceptance/bootstrap/SpacesTUSContext.php | 5 +- tests/acceptance/bootstrap/TUSContext.php | 29 +- .../apiSpacesShares/shareUploadTUS.feature | 6 +- 4 files changed, 147 insertions(+), 187 deletions(-) diff --git a/tests/acceptance/TestHelpers/TusClientWrapper.php b/tests/acceptance/TestHelpers/TusClientWrapper.php index 7c1e3900e84..21e95994a28 100644 --- a/tests/acceptance/TestHelpers/TusClientWrapper.php +++ b/tests/acceptance/TestHelpers/TusClientWrapper.php @@ -1,182 +1,134 @@ - + * @copyright Copyright (c) 2017 Nabin Magar nabin@jankaritech.com + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, + * as published by the Free Software Foundation; + * either version 3 of the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * + */ + namespace TestHelpers; -use http\Env\Response; -use TusPhp\File; use Carbon\Carbon; -use TusPhp\Config; -use Ramsey\Uuid\Uuid; -use TusPhp\Exception\TusException; use TusPhp\Exception\FileException; -use GuzzleHttp\ClientTrait; -use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Exception\ClientException; -use TusPhp\Exception\ConnectionException; +use Psr\Http\Message\ResponseInterface; use GuzzleHttp\Exception\GuzzleException; -use GuzzleHttp\Exception\ConnectException; use Symfony\Component\HttpFoundation\Response as HttpResponse; use ReflectionException; use TusPhp\Tus\Client; -class TusClientWrapper extends Client{ - public $client; - - /** - * Constructor for the TusClientWrapper. - * - * @param string $baseUri Base URI of the TUS server. - * @param array $options Additional client options. - * @throws ReflectionException - */ - public function __construct(string $baseUri, array $options = []) { - parent::__construct($baseUri,$options); - $this->client = new Client($baseUri,$options); - } - - public function setKey(string $key): self - { - $this->client->setKey($key); - return $this; - } - - public function file(string $file, string $name = null): self - { - $this->client->file($file,$name); - return $this; - } - - public function createWithUpload(string $key, int $bytes = -1): array { - $bytes = $bytes < 0 ? $this->fileSize : $bytes; - $headers = $this->headers + [ - 'Upload-Length' => $this->client->fileSize, - 'Upload-Key' => $key, - 'Upload-Checksum' => $this->client->getUploadChecksumHeader(), - 'Upload-Metadata' => $this->client->getUploadMetadataHeader(), - ]; - - $data = ''; - if ($bytes > 0) { - $data = $this->client->getData(0, $bytes); - - $headers += [ - 'Content-Type' => self::HEADER_CONTENT_TYPE, - 'Content-Length' => \strlen($data), - ]; - } - - if ($this->isPartial()) { - $headers += ['Upload-Concat' => 'partial']; - } - - try { - $response = $this->client->getClient()->post($this->apiPath, [ - 'body' => $data, - 'headers' => $headers, - ]); - } catch (ClientException $e) { - $response = $e->getResponse(); - } - - $statusCode = $response->getStatusCode(); - $header = $response->getHeaders(); - - - if (HttpResponse::HTTP_CREATED !== $statusCode) { - throw new FileException('Unable to create resource.'); - } - - $uploadOffset = $bytes > 0 ? current($response->getHeader('upload-offset')) : 0; - $uploadLocation = current($response->getHeader('location')); - - $this->getCache()->set($this->client->getKey(), [ - 'location' => $uploadLocation, - 'expires_at' => Carbon::now()->addSeconds($this->getCache()->getTtl())->format($this->getCache()::RFC_7231), - ]); - - return [ - 'location' => $uploadLocation, - 'offset' => $uploadOffset, - ]; - } - -// /** -// * Set API path. -// * -// * @param string $path -// * -// * @return self -// */ -// public function setApiPath(string $path): self -// { -// $this->client->apiPath = $path; -// return $this; -// } - -// public function setApiPath(string $path): self -// { -// $this->client->apiPath = $path; -// return $this; -// } - -// public function setKey(string $key): self -// { -// $this->client->setKey($key); -// return $this; -// } - -// public function file(string $file, string $name = null): self -// { -// $this->client->file($file,$name); -// return $this; -// } - -// public function createWithUpload(string $key, int $bytes = -1): void -// { -// $this->client->createWithUpload($key,$bytes); -// } - -// public function setHeaders(array $headers): void { -// $this->client->setHeaders($headers); -// } -// -// public function upload(string $filePath): string { -// $this->client->setFilePath($filePath); -// return $this->client->upload(); -// } -// -// public function getOffset(): int { -// return $this->client->getOffset(); -// } -// -// public function setChunkSize(int $bytes): void { -// $this->client->setChunkSize($bytes); -// } -// -// public function terminateUpload(string $uploadUrl): void { -// $this->client->terminate($uploadUrl); -// } -// -// public function setKey(string $key): self -// { -// $this->client->key = $key; -// -// return $this; -// } -// -// public function file(string $file, string $name = null): self -// { -// $this->filePath = $file; -// -// if ( ! file_exists($file) || ! is_readable($file)) { -// throw new FileException('Cannot read file: ' . $file); -// } -// -// $this->fileName = $name ?? basename($this->filePath); -// $this->fileSize = filesize($file); -// -// $this->addMetadata('filename', $this->fileName); -// -// return $this; -// } - +/** + * A helper class where TUS is wrapped and done API requests + */ + +class TusClientWrapper extends Client { + public $client; + + /** + * Constructor for the TusClientWrapper. + * + * @param string $baseUri + * @param array $options + * + * @throws ReflectionException + */ + public function __construct(string $baseUri, array $options = []) { + parent::__construct($baseUri, $options); + $this->client = new Client($baseUri, $options); + } + + /** + * @param string $key + * + * @return self + */ + public function setKey(string $key): self { + $this->client->setKey($key); + return $this; + } + + /** + * @param string $file + * @param string|null $name + * + * @return self + */ + public function file(string $file, string $name = null): self { + $this->client->file($file, $name); + return $this; + } + + /** + * @param string $key + * @param int $bytes + * + * @return ResponseInterface + * @throws GuzzleException + */ + public function createUploadWithResponse(string $key, int $bytes = -1): ResponseInterface { + $bytes = $bytes < 0 ? $this->fileSize : $bytes; + $headers = $this->headers + [ + 'Upload-Length' => $this->client->fileSize, + 'Upload-Key' => $key, + 'Upload-Checksum' => $this->client->getUploadChecksumHeader(), + 'Upload-Metadata' => $this->client->getUploadMetadataHeader(), + ]; + + $data = ''; + if ($bytes > 0) { + $data = $this->client->getData(0, $bytes); + + $headers += [ + 'Content-Type' => self::HEADER_CONTENT_TYPE, + 'Content-Length' => \strlen($data), + ]; + } + + if ($this->isPartial()) { + $headers += ['Upload-Concat' => 'partial']; + } + + try { + $response = $this->client->getClient()->post( + $this->apiPath, + [ + 'body' => $data, + 'headers' => $headers, + ] + ); + } catch (ClientException $e) { + $response = $e->getResponse(); + } + + $statusCode = $response->getStatusCode(); + + if ($statusCode !== HttpResponse::HTTP_CREATED) { + throw new FileException('Unable to create resource.'); + } + + $uploadLocation = current($response->getHeader('location')); + + $this->getCache()->set( + $this->client->getKey(), + [ + 'location' => $uploadLocation, + 'expires_at' => Carbon::now()->addSeconds($this->getCache()->getTtl())->format($this->getCache()::RFC_7231), + ] + ); + return $response; + } } diff --git a/tests/acceptance/bootstrap/SpacesTUSContext.php b/tests/acceptance/bootstrap/SpacesTUSContext.php index 3700b4e360a..ce597ccd860 100644 --- a/tests/acceptance/bootstrap/SpacesTUSContext.php +++ b/tests/acceptance/bootstrap/SpacesTUSContext.php @@ -98,15 +98,16 @@ public function userUploadsAFileViaTusInsideOfTheSpaceUsingTheWebdavApi( * @param string $password * * @return void - * @throws Exception + * @throws Exception|GuzzleException */ public function thePublicUploadsFileViaTusInsideLastSharedFolderWithPasswordUsingTheWebdavApi( string $source, string $destination, string $password ): void { - $this->tusContext->publicUploadFileUsingTus($source, $destination, $password); + $response = $this->tusContext->publicUploadFileUsingTus($source, $destination, $password); $this->featureContext->setLastUploadDeleteTime(\time()); + $this->featureContext->setResponse($response); } /** diff --git a/tests/acceptance/bootstrap/TUSContext.php b/tests/acceptance/bootstrap/TUSContext.php index 84cff4f4c8b..baa495e65a1 100644 --- a/tests/acceptance/bootstrap/TUSContext.php +++ b/tests/acceptance/bootstrap/TUSContext.php @@ -338,13 +338,15 @@ public function uploadFileUsingTus( * @param string $destination * @param string $password * - * @return void + * @return ResponseInterface + * @throws GuzzleException + * @throws ReflectionException */ public function publicUploadFileUsingTus( string $source, string $destination, string $password, - ): void { + ): ResponseInterface { $password = $this->featureContext->getActualPassword($password); if ($this->featureContext->isUsingSharingNG()) { $token = $this->featureContext->shareNgGetLastCreatedLinkShareToken(); @@ -357,17 +359,18 @@ public function publicUploadFileUsingTus( $sourceFile = $this->featureContext->acceptanceTestsDirLocation() . $source; $url = WebdavHelper::getDavPath(WebDavHelper::DAV_VERSION_SPACES, $token, "public-files"); - $tusWrapper = new TusClientWrapper( - $this->featureContext->getBaseUrl(), - [ - 'verify' => false, - 'headers' => $headers - ] - ); - - $tusWrapper->setApiPath($url); - $tusWrapper->setKey((string)rand())->file($sourceFile, $destination); - $tusWrapper->file($sourceFile, $destination)->createWithUpload("", 0); + $tusWrapper = new TusClientWrapper( + $this->featureContext->getBaseUrl(), + [ + 'verify' => false, + 'headers' => $headers + ] + ); + + $tusWrapper->setApiPath($url); + $tusWrapper->setKey((string)rand())->file($sourceFile, $destination); + $response = $tusWrapper->file($sourceFile, $destination)->createUploadWithResponse("", 0); + return $response; } /** diff --git a/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature b/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature index 1df471ddc5b..1beae0d9d33 100644 --- a/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature +++ b/tests/acceptance/features/apiSpacesShares/shareUploadTUS.feature @@ -445,7 +445,11 @@ Feature: upload resources on share using TUS protocol | permissionsRole | createOnly | | password | %public% | When the public uploads file "filesForUpload/zerobyte.txt" to "textfile.txt" via TUS inside last link shared folder with password "%public%" using the WebDAV API - Then for user "Alice" the space "Project" should contain these files: + Then the HTTP status code should be "201" + And the following headers should be set + | header | value | + | Access-Control-Expose-Headers | Tus-Resumable, Upload-Offset, Location | + And for user "Alice" the space "Project" should contain these files: | textfile.txt | And for user "Alice" the space "Project" should not contain these files: | textfile (1).txt |