The source prop for WebView allows for passing request headers. When the webview renders for the first time, the request headers are sent.
But when the links within that page are clicked, the headers are not sent to the server in the request header.
Similarly, when the goBack() method is called on the WebView, the request headers are not being sent.
+1. I got the same problem with version 30-rc
And it only exists on Android. My iOS app works normally.
We are seeing the problem on iOS
Any update on this? Facing the problem on both iOS and Android. Or anyone can point me in the right direction on how to fix this?
Reliable HTTP headers are important for many apps / APIs to work. Any update on this?
+1
Can you provide a sample rnplay.org app that reproduces this problem?
I'll see if @chiraggshah can provide a sample from our application however he's on holiday for the next 2.5 weeks.
react-native-cli: 1.3.0
react-native: 0.38.1
Android has the same problem, not test iOS.
I was wondering if anyone has a workaround or fix for this issue?
@alkhanna : I have written a blog with the workaround for this. http://blog.bigbinary.com/2016/07/26/passing-request-headers-on-each-webview-request-in-react-native.html
@lacker : I am not sure how to host own server which logs the headers received on each request using rnplay.org. Instead, I can paste a sample app here.
Server:
var http = require('http');
var port = 9000;
function logRequest(request) {
console.log("Processing request for: ", request.url)
console.log("Custom Header: ", request.headers["custom-app-header"])
console.log("Request Processed\n")
}
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
switch(request.url) {
case "/":
response.write("<html><body>Welcome<a href='/bye'>Bye</a></body></html>");
logRequest(request)
break;
case "/bye":
response.write("<html><body>Bye<a href='/'>Welcome</a></body></html>");
logRequest(request)
break;
default:
break;
}
response.end();
}).listen(port);
Webview Code:
<WebView
source={
{
uri: "http://localhost:3000",
headers: {"custom-app-header": "react-native-ios-app"}
}
}
/>
After starting the node server, the logs show the headers being passed for the first request sent by webview. But on subsequent page clicks, the header is not sent.
Let me know if I can be more descriptive, and I will do as required.
+1
@satya164 : Can you point me to the right person who possibly would have the insight on how to fix this? This is a long time issue and has not received much attention.
Or someone can guide me on how to fix it or where to start looking? That too would be a good start.
+1
+1
According the docs
source?: {uri: string, method: string, headers: object, body: string}, {html: string, baseUrl: string}, number
Loads static html or a uri (with optional headers) in the WebView.
This implies that only the first source uri request of the WebView will use the custom headers...
So, dumb question... but does this even suppose to work like you expect?
If you're iOS only, you can use this workaround (use as prop of your WebView, I assume you store the webview's url in this.state.source). Yeah, it sucks... hopefully this gets fixed soon.
onShouldStartLoadWithRequest={(request) => {
console.log('**** REQUEST.url: ' + request.url + '\n**** REQUEST.navigationType: ' + request.navigationType);
if (request.url === this.state.source) {
return true;
}
// HORRENDOUS hack: RN's WebView doesn't bother keeping headers around.
// So we always fail new requests, then update state to re-render with new URL
// NOTE: only works on iOS
this.setState({ source: request.url });
return false;
}}
@xaphod : You can use the workaround I posted above. That works for both iOS and Android
@chiraggshah Thanks, yes I saw your workaround. It has several disadvantages for me, chiefly hitting all endpoints twice. That's why I used a different workaround
react-native-cli: 2.0.1
react-native: 0.45.1
Facing the problem on iOS, no problem with Android.
@xaphod Your workaround is wonderful on iOS. My workaround is based on yours and I add an Array to save histories to enable goBack feature (iOS only).
historyUrl: string[] = new Array();
onShouldStartLoadWithRequest = (request) => {
let curUrl = this.state.url;
let newUrl = request.url;
if (newUrl === curUrl) {
return true;
}
this.historyUrl.push(curUrl);
this.setState({
url : newUrl
});
return false;
}
componentWillReceiveProps(nextProps) {
if (nextProps.goBack) {
if (this.historyUrl.length === 0) {
// exit
......
} else {
let newUrl = this.historyUrl.pop();
this.setState({
url : newUrl
});
}
}
}
For I haven't faced the problem on Android, so I use this.refs[WEBVIEW_REF].goBack() to enable goBack feature for Android.
However, there isn't onShouldStartLoadWithRequest function for Android.
So if you face the problem on Android, @chiraggshah 's workaround is the best way so far, but it will results in double-request.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.
This is still issue for me. Universal workaround above works only GET requests, but doesn't on POST.
I'm facing the same problem. It seems this bug is by design from the React team, so is it something that would likely be fixed or what's the reasoning behind it? It would be great to get some feedback from the React team.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.
This issue needs to be open because certain websites do expect api-token/auth-token or certain headers to be present in each request.
Any movement on this one? It's a pretty bad bug that forces horrible workarounds. Can someone on the RN team please acknowledge that this issue has been read and triaged?
Probably the right solution is to treat the WebView as a fully controlled component, similar to how an can take defaultValue and value.
So, if the WebView gets defaultSource, it continues to behave as it does today.
If the WebView gets a source attribute, it is then a fully controlled component. It should cancel all page transitions and provide a new callback, something like onChange(url, type, postBody) which can then be used up update the source attribute in the application code.
+1
+1
+1. @Red-Rock did you check android devices, with android 6.0 api-23 and lower for example?
+1
+1
+1
+1
+1
For anyone that needs this for basic authentication, in iOS you can set the authentication as part of the URL: https://user:[email protected] . Unfortunately this does not work for Android, for that I had to create a custom WebView and implement onReceivedHttpAuthRequest for its web client.
+1, running into this issue as well, it's extremely frustrating. Any updates?
Given how common hybrid apps are, and how common Basic Authentication is, I honestly think this deserves more attention. Taking into consideration that this issue has been open for almost two years now …
If the intention of source.headers is to simply provide custom headers with the first request, then you could provide a defaultHeaders-property for the web view, and still maintain backward compatibility. I would certainly not expect the "source headers" to get passed with each consecutive request.
A more "catch-all" solution would be to provide a onRequest-callback, where the user can modify the request as they see fit, for instance:
<WebView
onRequest={req => req.addHeader('Authorization', 'Basic c2VyaW91c2x5Ond0Zg==')}
/>
+1
facing the same issue
Migrated to https://github.com/react-native-community/react-native-webview/issues/4, so we can close this issue.
Closing here but we are committed to fix this and keep discussing on the new repo
Most helpful comment
+1, running into this issue as well, it's extremely frustrating. Any updates?
Given how common hybrid apps are, and how common Basic Authentication is, I honestly think this deserves more attention. Taking into consideration that this issue has been open for almost two years now …
If the intention of
source.headersis to simply provide custom headers with the first request, then you could provide adefaultHeaders-property for the web view, and still maintain backward compatibility. I would certainly not expect the "source headers" to get passed with each consecutive request.A more "catch-all" solution would be to provide a
onRequest-callback, where the user can modify the request as they see fit, for instance: