From 226b36c2a2b07bfb6c597f65566dd50ed97d96b4 Mon Sep 17 00:00:00 2001 From: realaboo Date: Sat, 26 Dec 2015 18:35:30 +0800 Subject: [PATCH] Get response url from XMLHttpRequest --- Examples/UIExplorer/XHRExample.android.js | 6 + Examples/UIExplorer/XHRExample.ios.js | 68 +---------- Examples/UIExplorer/XHRExampleFetch.js | 113 ++++++++++++++++++ Libraries/Network/RCTNetworking.m | 3 +- Libraries/Network/XMLHttpRequestBase.js | 6 +- .../modules/network/NetworkingModule.java | 1 + 6 files changed, 130 insertions(+), 67 deletions(-) create mode 100644 Examples/UIExplorer/XHRExampleFetch.js diff --git a/Examples/UIExplorer/XHRExample.android.js b/Examples/UIExplorer/XHRExample.android.js index 1dfb9a32cfe86c..5a46d8dd9751d3 100644 --- a/Examples/UIExplorer/XHRExample.android.js +++ b/Examples/UIExplorer/XHRExample.android.js @@ -28,6 +28,7 @@ var { var XHRExampleHeaders = require('./XHRExampleHeaders'); var XHRExampleCookies = require('./XHRExampleCookies'); +var XHRExampleFetch = require('./XHRExampleFetch'); // TODO t7093728 This is a simplified XHRExample.ios.js. @@ -281,6 +282,11 @@ exports.examples = [{ render() { return ; } +}, { + title: 'Fetch Test', + render() { + return ; + } }, { title: 'Headers', render() { diff --git a/Examples/UIExplorer/XHRExample.ios.js b/Examples/UIExplorer/XHRExample.ios.js index cc83ccf5837c0d..d8d370319aa864 100644 --- a/Examples/UIExplorer/XHRExample.ios.js +++ b/Examples/UIExplorer/XHRExample.ios.js @@ -31,6 +31,7 @@ var { } = React; var XHRExampleHeaders = require('./XHRExampleHeaders'); +var XHRExampleFetch = require('./XHRExampleFetch'); class Downloader extends React.Component { @@ -304,54 +305,6 @@ 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'; exports.description = 'XMLHttpRequest'; @@ -366,9 +319,9 @@ exports.examples = [{ return ; } }, { - title: 'fetch test', + title: 'Fetch Test', render() { - return ; + return ; } }, { title: 'Headers', @@ -432,19 +385,4 @@ 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/Examples/UIExplorer/XHRExampleFetch.js b/Examples/UIExplorer/XHRExampleFetch.js new file mode 100644 index 00000000000000..4f40842810160d --- /dev/null +++ b/Examples/UIExplorer/XHRExampleFetch.js @@ -0,0 +1,113 @@ +/** + * The examples provided by Facebook are for non-commercial testing and + * evaluation purposes only. + * + * Facebook reserves all rights not expressly granted. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL + * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @flow + */ +'use strict'; + +var React = require('react-native'); +var { + StyleSheet, + Text, + TextInput, + TouchableHighlight, + View, + Platform, +} = React; + + +class XHRExampleFetch extends React.Component { + + constructor(props) { + super(props); + this.state = { + responseText: null, + }; + this.responseURL = null; + } + + submit(uri: String) { + fetch(uri).then((response) => { + this.responseURL = response.url; + return response.text(); + }).then((body) => { + this.setState({responseText: body}); + }); + } + + render() { + + var responseURL = this.responseURL ? ( + + Server response URL: + {this.responseURL} + + ) : null; + + var response = this.state.responseText ? ( + + Server response: + + + ) : null; + + return ( + + Edit URL to submit: + { + this.submit(event.nativeEvent.text); + }} + style={styles.textInput} + /> + {responseURL} + {response} + + ); + } +} + +var styles = StyleSheet.create({ + textInput: { + flex: 1, + borderRadius: 3, + borderColor: 'grey', + borderWidth: 1, + height: Platform.OS === 'android' ? 44 : 30, + paddingLeft: 8, + }, + label: { + flex: 1, + color: '#aaa', + fontWeight: '500', + height: 20, + }, + textOutput: { + flex: 1, + fontSize: 17, + borderRadius: 3, + borderColor: 'grey', + borderWidth: 1, + height: 200, + paddingLeft: 8, + }, +}); + +module.exports = XHRExampleFetch; diff --git a/Libraries/Network/RCTNetworking.m b/Libraries/Network/RCTNetworking.m index 0c5aeaecd7fa7c..e36445f208f092 100644 --- a/Libraries/Network/RCTNetworking.m +++ b/Libraries/Network/RCTNetworking.m @@ -371,7 +371,8 @@ - (void)sendRequest:(NSURLRequest *)request headers = response.MIMEType ? @{@"Content-Type": response.MIMEType} : @{}; status = 200; } - NSArray *responseJSON = @[task.requestID, @(status), headers]; + id responseURL = response.URL ? response.URL.absoluteString : [NSNull null]; + NSArray *responseJSON = @[task.requestID, @(status), headers, responseURL]; [_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse" body:responseJSON]; }); diff --git a/Libraries/Network/XMLHttpRequestBase.js b/Libraries/Network/XMLHttpRequestBase.js index 6c7bb8b4863112..7ef91fb45962cb 100644 --- a/Libraries/Network/XMLHttpRequestBase.js +++ b/Libraries/Network/XMLHttpRequestBase.js @@ -69,6 +69,7 @@ class XMLHttpRequestBase { this.responseHeaders = undefined; this.responseText = ''; this.status = 0; + delete this.responseURL; this._requestId = null; @@ -110,11 +111,14 @@ class XMLHttpRequestBase { } } - _didReceiveResponse(requestId: number, status: number, responseHeaders: ?Object): void { + _didReceiveResponse(requestId: number, status: number, responseHeaders: ?Object, responseURL: ?string): void { if (requestId === this._requestId) { this.status = status; this.setResponseHeaders(responseHeaders); this.setReadyState(this.HEADERS_RECEIVED); + if (responseURL) { + this.responseURL = responseURL; + } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java index 728acf7fe99f62..d1f32616e6a46b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java @@ -289,6 +289,7 @@ private void onResponseReceived(int requestId, Response response) { args.pushInt(requestId); args.pushInt(response.code()); args.pushMap(headers); + args.pushString(response.request().urlString()); getEventEmitter().emit("didReceiveNetworkResponse", args); }