Skip to content

Commit bd9d6af

Browse files
committed
Fix 404 and 403 pulls of files leaving files on disk.
1 parent b7cd711 commit bd9d6af

File tree

5 files changed

+105
-27
lines changed

5 files changed

+105
-27
lines changed

react-native/services/Request/index.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ export class Request implements RequestInterface {
278278
queryParameters: QueryParameters,
279279
abortSignal: null,
280280
fileUri: string,
281-
expectedStatusCodes: ReadonlyArray<T>
281+
successfulStatusCodes: ReadonlyArray<T>,
282+
unsuccessfulStatusCodes: ReadonlyArray<T>
282283
): Promise<T> {
283284
// Not yet possible with FileSystem.downloadAsync.
284285
abortSignal;
@@ -293,7 +294,16 @@ export class Request implements RequestInterface {
293294
},
294295
});
295296

296-
this.checkStatusCode(method, url, response.status, expectedStatusCodes);
297+
this.checkStatusCode(method, url, response.status, [
298+
...successfulStatusCodes,
299+
...unsuccessfulStatusCodes,
300+
]);
301+
302+
// It's possible that the application will close before we hit this line,
303+
// but this is the best we can do unfortunately.
304+
if (unsuccessfulStatusCodes.includes(String(response.status) as T)) {
305+
await FileSystem.deleteAsync(fileUri, { idempotent: true });
306+
}
297307

298308
return String(response.status) as T;
299309
} catch (e) {

react-native/services/Request/unit.tsx

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,8 @@ test(`get request empty response file`, async () => {
14501450
},
14511451
null,
14521452
`Example File Uri`,
1453-
[`244`, `123`, `89`]
1453+
[`244`, `123`, `89`],
1454+
[`800`, `222`, `347`, `844`]
14541455
);
14551456

14561457
expect(response).toEqual(`123`);
@@ -1469,6 +1470,58 @@ test(`get request empty response file`, async () => {
14691470
expect(FileSystem.deleteAsync).not.toHaveBeenCalled();
14701471
});
14711472

1473+
test(`get request empty response file failure status code`, async () => {
1474+
const fetch = jest.fn();
1475+
(global as unknown as { fetch: unknown }).fetch = fetch;
1476+
(
1477+
FileSystem.downloadAsync as unknown as {
1478+
mockResolvedValue(value: unknown): void;
1479+
}
1480+
).mockResolvedValue({
1481+
status: 347,
1482+
});
1483+
const request = new Request(
1484+
`https://example-base-url.com/example/sub/path/`,
1485+
1000,
1486+
() => `Example Authorization Header`
1487+
);
1488+
1489+
const response = await request.returningFile(
1490+
`GET`,
1491+
`example/route`,
1492+
{ type: `empty` },
1493+
{
1494+
"Example Query Parameter A Key": `Example Query Parameter A Value`,
1495+
"Example Query Parameter B Key": 12.34,
1496+
"Example Query Parameter C Key": false,
1497+
"Example Query Parameter D Key": true,
1498+
},
1499+
null,
1500+
`Example File Uri`,
1501+
[`244`, `123`, `89`],
1502+
[`800`, `222`, `347`, `844`]
1503+
);
1504+
1505+
expect(response).toEqual(`347`);
1506+
1507+
expect(FileSystem.downloadAsync).toBeCalledTimes(1);
1508+
expect(FileSystem.downloadAsync).toBeCalledWith(
1509+
`https://example-base-url.com/example/sub/path/example/route?Example%20Query%20Parameter%20A%20Key=Example%20Query%20Parameter%20A%20Value&Example%20Query%20Parameter%20B%20Key=12.34&Example%20Query%20Parameter%20D%20Key`,
1510+
`Example File Uri`,
1511+
{
1512+
headers: { Authorization: `Example Authorization Header` },
1513+
}
1514+
);
1515+
1516+
expect(FileSystem.deleteAsync).toBeCalledTimes(1);
1517+
expect(FileSystem.deleteAsync).toBeCalledWith(`Example File Uri`, {
1518+
idempotent: true,
1519+
});
1520+
1521+
expect(FileSystem.createUploadTask).not.toHaveBeenCalled();
1522+
expect(fetch).not.toHaveBeenCalled();
1523+
});
1524+
14721525
test(`get request empty response file invalid status code`, async () => {
14731526
const fetch = jest.fn();
14741527
(global as unknown as { fetch: unknown }).fetch = fetch;
@@ -1497,7 +1550,8 @@ test(`get request empty response file invalid status code`, async () => {
14971550
},
14981551
null,
14991552
`Example File Uri`,
1500-
[`244`, `123`, `89`]
1553+
[`244`, `123`, `89`],
1554+
[`800`, `222`, `347`, `844`]
15011555
);
15021556

15031557
await expect(promise).rejects.toEqual(

react-native/services/Sync/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ export class Sync<
556556
{},
557557
null,
558558
this.fileStore.generatePath(file.uuid),
559-
[`200`, `404`, `403`]
559+
[`200`],
560+
[`404`, `403`]
560561
);
561562

562563
if (statusCode === `200`) {

react-native/services/Sync/unit.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ type PullFileStep = {
8888
readonly requestBody: EmptyRequestBody | JsonRequestBody | FileRequestBody;
8989
readonly queryParameters: QueryParameters;
9090
readonly fileUri: string;
91-
readonly expectedStatusCodes: ReadonlyArray<string>;
91+
readonly successfulStatusCodes: ReadonlyArray<string>;
92+
readonly failureStatusCodes: ReadonlyArray<string>;
9293
readonly statusCode: string;
9394
};
9495

@@ -423,7 +424,8 @@ function scenario(
423424
queryParameters,
424425
abortSignal,
425426
fileUri,
426-
expectedStatusCodes
427+
successfulStatusCodes,
428+
failureStatusCodes
427429
) => {
428430
const expectedStep = expectedSteps[actualSteps.length];
429431

@@ -434,7 +436,8 @@ function scenario(
434436
requestBody,
435437
queryParameters,
436438
fileUri,
437-
expectedStatusCodes,
439+
successfulStatusCodes,
440+
failureStatusCodes,
438441
statusCode: expect.anything(),
439442
});
440443

@@ -4886,7 +4889,8 @@ scenario(
48864889
requestBody: { type: `empty` },
48874890
queryParameters: {},
48884891
fileUri: `Example File Path For Uuid dab5ac6d-0ecc-4af9-9022-dda2414bf8b6 Generated By File Store`,
4889-
expectedStatusCodes: [`200`, `404`, `403`],
4892+
successfulStatusCodes: [`200`],
4893+
failureStatusCodes: [`404`, `403`],
48904894
statusCode: `200`,
48914895
},
48924896
{
@@ -4938,7 +4942,8 @@ scenario(
49384942
requestBody: { type: `empty` },
49394943
queryParameters: {},
49404944
fileUri: `Example File Path For Uuid 286b57fd-1551-4899-9f90-07e8727e4823 Generated By File Store`,
4941-
expectedStatusCodes: [`200`, `404`, `403`],
4945+
successfulStatusCodes: [`200`],
4946+
failureStatusCodes: [`404`, `403`],
49424947
statusCode: `200`,
49434948
},
49444949
{
@@ -5695,7 +5700,8 @@ scenario(
56955700
requestBody: { type: `empty` },
56965701
queryParameters: {},
56975702
fileUri: `Example File Path For Uuid 40d92d2c-631f-4a42-ba5e-a70a82bea897 Generated By File Store`,
5698-
expectedStatusCodes: [`200`, `404`, `403`],
5703+
successfulStatusCodes: [`200`],
5704+
failureStatusCodes: [`404`, `403`],
56995705
statusCode: `200`,
57005706
},
57015707
{
@@ -5747,7 +5753,8 @@ scenario(
57475753
requestBody: { type: `empty` },
57485754
queryParameters: {},
57495755
fileUri: `Example File Path For Uuid c2df927b-74be-4d78-8705-7f0a664ba53b Generated By File Store`,
5750-
expectedStatusCodes: [`200`, `404`, `403`],
5756+
successfulStatusCodes: [`200`],
5757+
failureStatusCodes: [`404`, `403`],
57515758
statusCode: `200`,
57525759
},
57535760
{
@@ -7135,7 +7142,8 @@ scenario(
71357142
requestBody: { type: `empty` },
71367143
queryParameters: {},
71377144
fileUri: `Example File Path For Uuid bdf19add-072c-4fd6-bca7-8468f8b80a76 Generated By File Store`,
7138-
expectedStatusCodes: [`200`, `404`, `403`],
7145+
successfulStatusCodes: [`200`],
7146+
failureStatusCodes: [`404`, `403`],
71397147
statusCode: `200`,
71407148
},
71417149
{
@@ -16071,7 +16079,8 @@ scenario(
1607116079
requestBody: { type: `empty` },
1607216080
queryParameters: {},
1607316081
fileUri: `Example File Path For Uuid dab5ac6d-0ecc-4af9-9022-dda2414bf8b6 Generated By File Store`,
16074-
expectedStatusCodes: [`200`, `404`, `403`],
16082+
successfulStatusCodes: [`200`],
16083+
failureStatusCodes: [`404`, `403`],
1607516084
statusCode: `403`,
1607616085
},
1607716086
{
@@ -16392,7 +16401,8 @@ scenario(
1639216401
requestBody: { type: `empty` },
1639316402
queryParameters: {},
1639416403
fileUri: `Example File Path For Uuid 40d92d2c-631f-4a42-ba5e-a70a82bea897 Generated By File Store`,
16395-
expectedStatusCodes: [`200`, `404`, `403`],
16404+
successfulStatusCodes: [`200`],
16405+
failureStatusCodes: [`404`, `403`],
1639616406
statusCode: `403`,
1639716407
},
1639816408
{

react-native/types/RequestInterface/index.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,19 @@ export interface RequestInterface {
7878
/**
7979
* Performs a request which returns a file. NOTE: timeouts are not yet
8080
* available for this method.
81-
* @template T The expected response status code(s).
82-
* @param method The HTTP method to use.
83-
* @param route The URL path relative to the base URL.
84-
* @param requestBody The request body to send.
85-
* @param queryParameters The query parameters to include in the URL.
86-
* @param abortSignal When non-null, an AbortController's signal which
87-
* may be used to remotely cancel the request.
88-
* @param fileUri The URI to which the returned file is to be
89-
* downloaded.
90-
* @param expectedStatusCodes The status codes expected to be returned.
91-
* @returns The returned status code.
81+
* @template T The expected response status code(s).
82+
* @param method The HTTP method to use.
83+
* @param route The URL path relative to the base URL.
84+
* @param requestBody The request body to send.
85+
* @param queryParameters The query parameters to include in the URL.
86+
* @param abortSignal When non-null, an AbortController's signal
87+
* which may be used to remotely cancel the
88+
* request.
89+
* @param fileUri The URI to which the returned file is to be
90+
* downloaded.
91+
* @param successfulStatusCodes The status codes which indicate success.
92+
* @param unsuccessfulStatusCodes The status codes which indicate failure.
93+
* @returns The returned status code.
9294
*/
9395
returningFile<T extends string>(
9496
method: `GET`,
@@ -97,6 +99,7 @@ export interface RequestInterface {
9799
queryParameters: QueryParameters,
98100
abortSignal: null,
99101
fileUri: string,
100-
expectedStatusCodes: ReadonlyArray<T>
102+
successfulStatusCodes: ReadonlyArray<T>,
103+
unsuccessfulStatusCodes: ReadonlyArray<T>
101104
): Promise<T>;
102105
}

0 commit comments

Comments
 (0)