Skip to content

Commit

Permalink
Added logic to detect text encoding for downloaded data
Browse files Browse the repository at this point in the history
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: facebook#1780 (comment) 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
  • Loading branch information
nicklockwood authored and PublicParadise committed Sep 16, 2015
1 parent 00149b2 commit 54aee9d
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 deletions.
67 changes: 67 additions & 0 deletions Examples/UIExplorer/XHRExample.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? (
<View style={{marginTop: 10}}>
<Text style={styles.label}>Server response:</Text>
<TextInput
editable={false}
multiline={true}
defaultValue={this.state.responseText}
style={styles.textOutput}
/>
</View>
) : null;

return (
<View>
<Text style={styles.label}>Edit URL to submit:</Text>
<TextInput
returnKeyType="go"
defaultValue="http://www.posttestserver.com/post.php"
onSubmitEditing={(event)=> {
this.submit(event.nativeEvent.text);
}}
style={styles.textInput}
/>
{response}
</View>
);
}
}

exports.framework = 'React';
exports.title = 'XMLHttpRequest';
Expand All @@ -316,6 +363,11 @@ exports.examples = [{
render() {
return <FormUploader/>;
}
}, {
title: 'fetch test',
render() {
return <FetchTest/>;
}
}];

var styles = StyleSheet.create({
Expand Down Expand Up @@ -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,
},
});
21 changes: 19 additions & 2 deletions Libraries/Network/RCTNetworking.m
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,27 @@ - (void)sendData:(NSData *)data forTask:(RCTDownloadTask *)task
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 ?: @""];
Expand Down

0 comments on commit 54aee9d

Please sign in to comment.