Skip to content

Commit 09fd76b

Browse files
committed
fix: multipart testing
1 parent 3c8efda commit 09fd76b

34 files changed

+974
-651
lines changed

docs/account.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ This endpoint can also be used to convert an anonymous account to a normal one,
4242
| email | string | User email. | |
4343
| password | string | User password. Must be at least 8 chars. | |
4444

45-
## List Identities
45+
## List identities
4646

4747
```http request
4848
GET https://cloud.appwrite.io/v1/account/identities
@@ -106,7 +106,7 @@ PATCH https://cloud.appwrite.io/v1/account/mfa
106106
| --- | --- | --- | --- |
107107
| mfa | boolean | Enable or disable MFA. | |
108108

109-
## Create Authenticator
109+
## Create authenticator
110110

111111
```http request
112112
POST https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
@@ -120,7 +120,7 @@ POST https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
120120
| --- | --- | --- | --- |
121121
| type | string | **Required** Type of authenticator. Must be `totp` | |
122122

123-
## Verify Authenticator
123+
## Verify authenticator
124124

125125
```http request
126126
PUT https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
@@ -135,7 +135,7 @@ PUT https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
135135
| type | string | **Required** Type of authenticator. | |
136136
| otp | string | Valid verification token. | |
137137

138-
## Delete Authenticator
138+
## Delete authenticator
139139

140140
```http request
141141
DELETE https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
@@ -149,7 +149,7 @@ DELETE https://cloud.appwrite.io/v1/account/mfa/authenticators/{type}
149149
| --- | --- | --- | --- |
150150
| type | string | **Required** Type of authenticator. | |
151151

152-
## Create MFA Challenge
152+
## Create MFA challenge
153153

154154
```http request
155155
POST https://cloud.appwrite.io/v1/account/mfa/challenge
@@ -163,7 +163,7 @@ POST https://cloud.appwrite.io/v1/account/mfa/challenge
163163
| --- | --- | --- | --- |
164164
| factor | string | Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`. | |
165165

166-
## Create MFA Challenge (confirmation)
166+
## Create MFA challenge (confirmation)
167167

168168
```http request
169169
PUT https://cloud.appwrite.io/v1/account/mfa/challenge
@@ -178,31 +178,31 @@ PUT https://cloud.appwrite.io/v1/account/mfa/challenge
178178
| challengeId | string | ID of the challenge. | |
179179
| otp | string | Valid verification token. | |
180180

181-
## List Factors
181+
## List factors
182182

183183
```http request
184184
GET https://cloud.appwrite.io/v1/account/mfa/factors
185185
```
186186

187187
** List the factors available on the account to be used as a MFA challange. **
188188

189-
## Get MFA Recovery Codes
189+
## Get MFA recovery codes
190190

191191
```http request
192192
GET https://cloud.appwrite.io/v1/account/mfa/recovery-codes
193193
```
194194

195195
** Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes. **
196196

197-
## Create MFA Recovery Codes
197+
## Create MFA recovery codes
198198

199199
```http request
200200
POST https://cloud.appwrite.io/v1/account/mfa/recovery-codes
201201
```
202202

203203
** Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) method. **
204204

205-
## Regenerate MFA Recovery Codes
205+
## Regenerate MFA recovery codes
206206

207207
```http request
208208
PATCH https://cloud.appwrite.io/v1/account/mfa/recovery-codes

docs/examples/functions/create-deployment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
33
use Appwrite\Client;
4-
use Appwrite\InputFile;
4+
use Appwrite\Payload;
55
use Appwrite\Services\Functions;
66
77
$client = (new Client())
@@ -13,7 +13,7 @@ $functions = new Functions($client);
1313

1414
$result = $functions->createDeployment(
1515
functionId: '<FUNCTION_ID>',
16-
code: InputFile::withPath('file.png'),
16+
code: Payload::fromFile('file.png'),
1717
activate: false,
1818
entrypoint: '<ENTRYPOINT>', // optional
1919
commands: '<COMMANDS>' // optional

docs/examples/functions/create-execution.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
33
use Appwrite\Client;
4+
use Appwrite\Payload;
45
use Appwrite\Services\Functions;
56
67
$client = (new Client())
@@ -12,7 +13,7 @@ $functions = new Functions($client);
1213

1314
$result = $functions->createExecution(
1415
functionId: '<FUNCTION_ID>',
15-
body: '<BODY>', // optional
16+
body: Payload::fromJson([ 'x' => 'y' ]), // optional
1617
async: false, // optional
1718
path: '<PATH>', // optional
1819
method: ExecutionMethod::GET(), // optional

docs/examples/storage/create-file.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
33
use Appwrite\Client;
4-
use Appwrite\InputFile;
4+
use Appwrite\Payload;
55
use Appwrite\Services\Storage;
66
77
$client = (new Client())
@@ -14,6 +14,6 @@ $storage = new Storage($client);
1414
$result = $storage->createFile(
1515
bucketId: '<BUCKET_ID>',
1616
fileId: '<FILE_ID>',
17-
file: InputFile::withPath('file.png'),
17+
file: Payload::fromFile('file.png'),
1818
permissions: ["read("any")"] // optional
1919
);

docs/functions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ POST https://cloud.appwrite.io/v1/functions/{functionId}/executions
280280
| Field Name | Type | Description | Default |
281281
| --- | --- | --- | --- |
282282
| functionId | string | **Required** Function ID. | |
283-
| body | string | HTTP body of execution. Default value is empty string. | |
283+
| body | payload | HTTP body of execution. Default value is empty string. | |
284284
| async | boolean | Execute code in the background. Default value is false. | |
285285
| path | string | HTTP path of execution. Path can include query params. Default value is / | / |
286286
| method | string | HTTP method of execution. Default value is GET. | POST |

docs/locale.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ GET https://cloud.appwrite.io/v1/locale
1010

1111
([IP Geolocation by DB-IP](https://db-ip.com)) **
1212

13-
## List Locale Codes
13+
## List locale codes
1414

1515
```http request
1616
GET https://cloud.appwrite.io/v1/locale/codes

docs/storage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ PUT https://cloud.appwrite.io/v1/storage/buckets/{bucketId}/files/{fileId}
161161
| name | string | Name of the file | |
162162
| permissions | array | An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions). | |
163163

164-
## Delete File
164+
## Delete file
165165

166166
```http request
167167
DELETE https://cloud.appwrite.io/v1/storage/buckets/{bucketId}/files/{fileId}

docs/users.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ POST https://cloud.appwrite.io/v1/users/bcrypt
6767
| password | string | User password hashed using Bcrypt. | |
6868
| name | string | User name. Max length: 128 chars. | |
6969

70-
## List Identities
70+
## List identities
7171

7272
```http request
7373
GET https://cloud.appwrite.io/v1/users/identities
@@ -310,7 +310,7 @@ PATCH https://cloud.appwrite.io/v1/users/{userId}/mfa
310310
| userId | string | **Required** User ID. | |
311311
| mfa | boolean | Enable or disable MFA. | |
312312

313-
## Delete Authenticator
313+
## Delete authenticator
314314

315315
```http request
316316
DELETE https://cloud.appwrite.io/v1/users/{userId}/mfa/authenticators/{type}
@@ -325,7 +325,7 @@ DELETE https://cloud.appwrite.io/v1/users/{userId}/mfa/authenticators/{type}
325325
| userId | string | **Required** User ID. | |
326326
| type | string | **Required** Type of authenticator. | |
327327

328-
## List Factors
328+
## List factors
329329

330330
```http request
331331
GET https://cloud.appwrite.io/v1/users/{userId}/mfa/factors
@@ -339,7 +339,7 @@ GET https://cloud.appwrite.io/v1/users/{userId}/mfa/factors
339339
| --- | --- | --- | --- |
340340
| userId | string | **Required** User ID. | |
341341

342-
## Get MFA Recovery Codes
342+
## Get MFA recovery codes
343343

344344
```http request
345345
GET https://cloud.appwrite.io/v1/users/{userId}/mfa/recovery-codes
@@ -353,7 +353,7 @@ GET https://cloud.appwrite.io/v1/users/{userId}/mfa/recovery-codes
353353
| --- | --- | --- | --- |
354354
| userId | string | **Required** User ID. | |
355355

356-
## Regenerate MFA Recovery Codes
356+
## Regenerate MFA recovery codes
357357

358358
```http request
359359
PUT https://cloud.appwrite.io/v1/users/{userId}/mfa/recovery-codes
@@ -367,7 +367,7 @@ PUT https://cloud.appwrite.io/v1/users/{userId}/mfa/recovery-codes
367367
| --- | --- | --- | --- |
368368
| userId | string | **Required** User ID. | |
369369

370-
## Create MFA Recovery Codes
370+
## Create MFA recovery codes
371371

372372
```http request
373373
PATCH https://cloud.appwrite.io/v1/users/{userId}/mfa/recovery-codes
@@ -529,7 +529,7 @@ PATCH https://cloud.appwrite.io/v1/users/{userId}/status
529529
| userId | string | **Required** User ID. | |
530530
| status | boolean | User Status. To activate the user pass `true` and to block the user pass `false`. | |
531531

532-
## List User Targets
532+
## List user targets
533533

534534
```http request
535535
GET https://cloud.appwrite.io/v1/users/{userId}/targets
@@ -544,7 +544,7 @@ GET https://cloud.appwrite.io/v1/users/{userId}/targets
544544
| userId | string | **Required** User ID. | |
545545
| queries | array | Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels | [] |
546546

547-
## Create User Target
547+
## Create user target
548548

549549
```http request
550550
POST https://cloud.appwrite.io/v1/users/{userId}/targets
@@ -563,7 +563,7 @@ POST https://cloud.appwrite.io/v1/users/{userId}/targets
563563
| providerId | string | Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used. | |
564564
| name | string | Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23. | |
565565

566-
## Get User Target
566+
## Get user target
567567

568568
```http request
569569
GET https://cloud.appwrite.io/v1/users/{userId}/targets/{targetId}
@@ -578,7 +578,7 @@ GET https://cloud.appwrite.io/v1/users/{userId}/targets/{targetId}
578578
| userId | string | **Required** User ID. | |
579579
| targetId | string | **Required** Target ID. | |
580580

581-
## Update User target
581+
## Update user target
582582

583583
```http request
584584
PATCH https://cloud.appwrite.io/v1/users/{userId}/targets/{targetId}

src/Appwrite/Client.php

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class Client
5050
public function __construct()
5151
{
5252
$this->headers['X-Appwrite-Response-Format'] = '1.6.0';
53-
5453
}
5554

5655
/**
@@ -177,7 +176,7 @@ public function setEndpoint(string $endpoint): Client
177176
public function addHeader(string $key, string $value): Client
178177
{
179178
$this->headers[strtolower($key)] = $value;
180-
179+
181180
return $this;
182181
}
183182

@@ -211,6 +210,7 @@ public function call(
211210
break;
212211

213212
case 'multipart/form-data':
213+
$headers['accept'] = 'multipart/form-data';
214214
$query = $this->flatten($params);
215215
break;
216216

@@ -262,17 +262,23 @@ public function call(
262262
echo 'Warning: ' . $warning . PHP_EOL;
263263
}
264264
}
265-
265+
266266
switch(substr($contentType, 0, strpos($contentType, ';'))) {
267267
case 'application/json':
268268
$responseBody = json_decode($responseBody, true);
269269
break;
270270
}
271-
271+
if (str_contains($contentType, 'multipart/form-data')) {
272+
$matches = [];
273+
preg_match('/(?<boundary>[-]+[\w]+)--/m', $responseBody, $matches);
274+
if (isset($matches['boundary'])) {
275+
$responseBody = self::handleFormData($matches['boundary'], $responseBody);
276+
}
277+
}
272278
if (curl_errno($ch)) {
273279
throw new AppwriteException(curl_error($ch), $responseStatus, $responseBody['type'] ?? '', $responseBody);
274280
}
275-
281+
276282
curl_close($ch);
277283

278284
if($responseStatus >= 400) {
@@ -303,14 +309,76 @@ protected function flatten(array $data, string $prefix = ''): array {
303309
foreach($data as $key => $value) {
304310
$finalKey = $prefix ? "{$prefix}[{$key}]" : $key;
305311

306-
if (is_array($value)) {
307-
$output += $this->flatten($value, $finalKey); // @todo: handle name collision here if needed
308-
}
309-
else {
312+
if ($value instanceof Payload) {
313+
if ($value->filename) {
314+
if (class_exists('\CURLStringFile')) {
315+
// Use CURLStringFile for in-memory data (PHP 8.1+)
316+
$output[$finalKey] = new \CURLStringFile(
317+
$value->toBinary(),
318+
$value->filename,
319+
$value->mimeType
320+
);
321+
} else {
322+
// For PHP versions < 8.1, write data to a temporary file
323+
$tmpfname = tempnam(sys_get_temp_dir(), 'upload');
324+
file_put_contents($tmpfname, $value->toBinary());
325+
$output[$finalKey] = new \CURLFile(
326+
$tmpfname,
327+
$value->mimeType,
328+
$value->filename
329+
);
330+
}
331+
} else {
332+
$output[$finalKey] = $value->toBinary();
333+
}
334+
} else if (is_array($value)) {
335+
$output += $this->flatten($value, $finalKey);
336+
} else {
310337
$output[$finalKey] = $value;
311338
}
312339
}
313340

314341
return $output;
315342
}
343+
344+
public static function handleFormData(string $boundary, mixed $responseBody)
345+
{
346+
$parts = explode($boundary, $responseBody);
347+
$data = [];
348+
foreach ($parts as $part) {
349+
$lines = array_values(array_filter(explode("\r\n", $part)));
350+
$matches = [];
351+
$matched = preg_match('/name="?(?<name>\w+)/s', $part, $matches);
352+
if ($matched) {
353+
array_shift($lines);
354+
if(isset($lines[0]) && $lines[0] === 'Content-Type: application/json'){
355+
array_shift($lines);
356+
$json = json_decode(implode($lines), true);
357+
358+
if (count($json) > 0 && isset($json[0]['name']) && isset($json[0]['value'])) {
359+
$json = array_combine(
360+
array_map(fn($header) => $header['name'], $json),
361+
array_map(fn($header) => $header['value'], $json)
362+
);
363+
}
364+
365+
$data[$matches['name']] = $json;
366+
continue;
367+
}
368+
$data[$matches['name']] = implode("\r\n",$lines) ?? '';;
369+
}
370+
}
371+
372+
if(isset($data['responseStatusCode'])) {
373+
$data['responseStatusCode'] = (int) ($data['responseStatusCode'] ?? '');
374+
}
375+
if(isset($data['duration'])) {
376+
$data['duration'] = ((float) ($data['duration'] ?? ''));
377+
}
378+
if(isset($data['responseBody'])) {
379+
$data['responseBody'] = Payload::fromBinary($data['responseBody'] ?? '');
380+
}
381+
382+
return $data;
383+
}
316384
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy