From 0044b3c2c34127de65208f2f366b1f41ef043f3a Mon Sep 17 00:00:00 2001 From: Nick Lockwood Date: Wed, 16 Sep 2015 07:40:14 -0700 Subject: [PATCH] Added logic to detect text encoding for downloaded data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @​public RCTNetworking currently relies on network responses to include an accurate text encoding, otherwise it is unable to convert the response data to text unless it's encoded as UTF8. See: https://github.com/facebook/react-native/issues/1780#issuecomment-139334294 for details. This diff makes use of a new feature in iOS8 to detect the encoding of the text authomatically Reviewed By: @sahrens Differential Revision: D2443446 --- Examples/UIExplorer/XHRExample.ios.js | 67 +++++++++++++++++++++++++++ Libraries/Network/RCTNetworking.m | 21 ++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Examples/UIExplorer/XHRExample.ios.js b/Examples/UIExplorer/XHRExample.ios.js index 250061f1f4..57f7fc31ee 100644 --- a/Examples/UIExplorer/XHRExample.ios.js +++ b/Examples/UIExplorer/XHRExample.ios.js @@ -302,6 +302,53 @@ class FormUploader extends React.Component { } } +class FetchTest extends React.Component { + + constructor(props) { + super(props); + this.state = { + responseText: null, + }; + } + + submit(uri: String) { + fetch(uri).then((response) => { + return response.text(); + }).then((body) => { + this.setState({responseText: body}); + }); + } + + render() { + + var response = this.state.responseText ? ( + + Server response: + + + ) : null; + + return ( + + Edit URL to submit: + { + this.submit(event.nativeEvent.text); + }} + style={styles.textInput} + /> + {response} + + ); + } +} exports.framework = 'React'; exports.title = 'XMLHttpRequest'; @@ -316,6 +363,11 @@ exports.examples = [{ render() { return ; } +}, { + title: 'fetch test', + render() { + return ; + } }]; var styles = StyleSheet.create({ @@ -373,4 +425,19 @@ var styles = StyleSheet.create({ fontSize: 16, fontWeight: '500', }, + label: { + flex: 1, + color: '#aaa', + fontWeight: '500', + height: 20, + }, + textOutput: { + flex: 1, + fontSize: 17, + borderRadius: 3, + borderColor: 'grey', + borderWidth: 1, + height: 200, + paddingLeft: 8, + }, }); diff --git a/Libraries/Network/RCTNetworking.m b/Libraries/Network/RCTNetworking.m index 4853beff8f..7621eada9c 100644 --- a/Libraries/Network/RCTNetworking.m +++ b/Libraries/Network/RCTNetworking.m @@ -271,10 +271,27 @@ RCT_EXPORT_MODULE() encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); } + // Attempt to decode text NSString *responseText = [[NSString alloc] initWithData:data encoding:encoding]; if (!responseText && data.length) { - RCTLogWarn(@"Received data was invalid."); - return; + + // We don't have an encoding, or the encoding is incorrect, so now we + // try to guess (unfortunately, this feature is available of iOS 8+ only) + if ([NSString respondsToSelector:@selector(stringEncodingForData: + encodingOptions: + convertedString: + usedLossyConversion:)]) { + [NSString stringEncodingForData:data + encodingOptions:nil + convertedString:&responseText + usedLossyConversion:NULL]; + } + + // If we still can't decode it, bail out + if (!responseText) { + RCTLogWarn(@"Received data was not a string, or was not a recognised encoding."); + return; + } } NSArray *responseJSON = @[task.requestID, responseText ?: @""];