XHR: support typed arrays for request payloads

Summary:
Support `xhr.send(data)` for typed arrays.

**Test plan:** run UIExplorer example on iOS and Android.
Closes https://github.com/facebook/react-native/pull/11904

Differential Revision: D4425551

fbshipit-source-id: 065ab5873407a406ca4a831068ab138606c3361b
This commit is contained in:
Philipp von Weitershausen
2017-01-20 18:40:28 -08:00
committed by Facebook Github Bot
parent 116916b98d
commit 16bb6e87ba
11 changed files with 293 additions and 63 deletions

View File

@@ -16,9 +16,14 @@
const FormData = require('FormData');
const NativeEventEmitter = require('NativeEventEmitter');
const RCTNetworkingNative = require('NativeModules').Networking;
const convertRequestBody = require('convertRequestBody');
import type {RequestBody} from 'convertRequestBody';
type Header = [string, string];
// Convert FormData headers to arrays, which are easier to consume in
// native on Android.
function convertHeadersMapToArray(headers: Object): Array<Header> {
const headerArray = [];
for (const name in headers) {
@@ -47,16 +52,19 @@ class RCTNetworking extends NativeEventEmitter {
trackingName: string,
url: string,
headers: Object,
data: string | FormData | {uri: string},
data: RequestBody,
responseType: 'text' | 'base64',
incrementalUpdates: boolean,
timeout: number,
callback: (requestId: number) => any
) {
const body =
typeof data === 'string' ? {string: data} :
data instanceof FormData ? {formData: getParts(data)} :
data;
const body = convertRequestBody(data);
if (body && body.formData) {
body.formData = body.formData.map((part) => ({
...part,
headers: convertHeadersMapToArray(part.headers),
}));
}
const requestId = generateRequestId();
RCTNetworkingNative.sendRequest(
method,
@@ -80,11 +88,4 @@ class RCTNetworking extends NativeEventEmitter {
}
}
function getParts(data) {
return data.getParts().map((part) => {
part.headers = convertHeadersMapToArray(part.headers);
return part;
});
}
module.exports = new RCTNetworking();

View File

@@ -14,6 +14,9 @@
const FormData = require('FormData');
const NativeEventEmitter = require('NativeEventEmitter');
const RCTNetworkingNative = require('NativeModules').Networking;
const convertRequestBody = require('convertRequestBody');
import type {RequestBody} from 'convertRequestBody';
class RCTNetworking extends NativeEventEmitter {
@@ -26,16 +29,13 @@ class RCTNetworking extends NativeEventEmitter {
trackingName: string,
url: string,
headers: Object,
data: string | FormData | {uri: string},
data: RequestBody,
responseType: 'text' | 'base64',
incrementalUpdates: boolean,
timeout: number,
callback: (requestId: number) => any
) {
const body =
typeof data === 'string' ? {string: data} :
data instanceof FormData ? {formData: data.getParts()} :
data;
const body = convertRequestBody(data);
RCTNetworkingNative.sendRequest({
method,
url,

View File

@@ -303,6 +303,11 @@ RCT_EXPORT_MODULE()
if (body) {
return callback(nil, @{@"body": body});
}
NSString *base64String = [RCTConvert NSString:query[@"base64"]];
if (base64String) {
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
return callback(nil, @{@"body": data});
}
NSURLRequest *request = [RCTConvert NSURLRequest:query[@"uri"]];
if (request) {

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule convertRequestBody
* @flow
*/
'use strict';
const binaryToBase64 = require('binaryToBase64');
const FormData = require('FormData');
export type RequestBody =
string
| FormData
| {uri: string}
| ArrayBuffer
| $ArrayBufferView
;
function convertRequestBody(body: RequestBody): Object {
if (typeof body === 'string') {
return {string: body};
}
if (body instanceof FormData) {
return {formData: body.getParts()};
}
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) {
// $FlowFixMe: no way to assert that 'body' is indeed an ArrayBufferView
return {base64: binaryToBase64(body)};
}
return body;
}
module.exports = convertRequestBody;