Skip to content

Commit 32f6ec1

Browse files
author
alicata
committed
added headers parameter to append function allowing to set custom headers for every part of a form data, added custom headers handling for each part in getParts function
1 parent 33cdd24 commit 32f6ec1

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

packages/react-native/Libraries/Network/FormData.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
'use strict';
1212

1313
type FormDataValue = string | {name?: string, type?: string, uri: string};
14-
type FormDataNameValuePair = [string, FormDataValue];
14+
type FormDataNameValueTuple = [string, FormDataValue, Headers];
1515

1616
type Headers = {[name: string]: string, ...};
1717
type FormDataPart =
@@ -44,24 +44,25 @@ type FormDataPart =
4444
* body.append('authToken', 'secret');
4545
* body.append('photo', photo);
4646
* body.append('title', 'A beautiful photo!');
47+
* body.append('someInfo', JSON.stringify({date:new Date()}, { "content-type": "application/json" }));
4748
*
4849
* xhr.open('POST', serverURL);
4950
* xhr.send(body);
5051
*/
5152
class FormData {
52-
_parts: Array<FormDataNameValuePair>;
53+
_parts: Array<FormDataNameValueTuple>;
5354

5455
constructor() {
5556
this._parts = [];
5657
}
5758

58-
append(key: string, value: FormDataValue) {
59+
append(key: string, value: FormDataValue, headers?: Headers) {
5960
// The XMLHttpRequest spec doesn't specify if duplicate keys are allowed.
6061
// MDN says that any new values should be appended to existing values.
6162
// In any case, major browsers allow duplicate keys, so that's what we'll do
6263
// too. They'll simply get appended as additional form data parts in the
6364
// request body, leaving the server to deal with them.
64-
this._parts.push([key, value]);
65+
this._parts.push([key, value, headers]);
6566
}
6667

6768
getAll(key: string): Array<FormDataValue> {
@@ -71,20 +72,26 @@ class FormData {
7172
}
7273

7374
getParts(): Array<FormDataPart> {
74-
return this._parts.map(([name, value]) => {
75-
const contentDisposition = 'form-data; name="' + name + '"';
76-
77-
const headers: Headers = {'content-disposition': contentDisposition};
78-
75+
return this._parts.map(([name, value, originalHeaders]) => {
76+
if (!originalHeaders) {
77+
originalHeaders = {};
78+
}
79+
const isContentDispositionNeeded =
80+
!originalHeaders['content-disposition'];
81+
const contentDisposition: Partial<Headers> = isContentDispositionNeeded
82+
? {'content-disposition': 'form-data; name="' + name + '"'}
83+
: {};
84+
const headers: Headers = {
85+
...originalHeaders,
86+
...contentDisposition,
87+
};
7988
// The body part is a "blob", which in React Native just means
8089
// an object with a `uri` attribute. Optionally, it can also
8190
// have a `name` and `type` attribute to specify filename and
8291
// content type (cf. web Blob interface.)
8392
if (typeof value === 'object' && !Array.isArray(value) && value) {
84-
if (typeof value.name === 'string') {
85-
headers['content-disposition'] += `; filename="${
86-
value.name
87-
}"; filename*=utf-8''${encodeURI(value.name)}`;
93+
if (typeof value.name === 'string' && isContentDispositionNeeded) {
94+
headers['content-disposition'] += '; filename="' + value.name + '"';
8895
}
8996
if (typeof value.type === 'string') {
9097
headers['content-type'] = value.type;

packages/react-native/types/modules/globals.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ type FormDataPart =
111111
};
112112

113113
declare class FormData {
114-
append(name: string, value: any): void;
114+
append(name: string, value: any, headers: {[key: string]: string}): void;
115115
getAll(): Array<FormDataValue>;
116116
getParts(): Array<FormDataPart>;
117117
}

0 commit comments

Comments
 (0)