为了给你上下文,我们的应用程序是一个反应-本机的网页包装(类似于科多瓦或离子所做的)。
应用程序在用户打开应用程序后下载本地存储的web包的更新版本,然后WebView组件将其用作向用户显示应用程序的源。
这个web应用程序有一些部分使用web套接字,所以问题是,考虑到它的大流量,套接字/交换服务有一堆节点/副本,为了保持连接的活力,负载平衡器使用Set-Cookie头来确保客户端在每个请求中都到达正确的服务节点。
所以,我们要做的是:
我们的本机应用程序如下所示:
import React from 'react';
import {Platform, StyleSheet, View} from 'react-native';
import {WebView} from 'react-native-webview';
type WrapperProps = {
path: string;
};
function Wrapper({path}: WrapperProps) {
return (
<View style={styles.container}>
<WebView
allowFileAccess
allowUniversalAccessFromFileURLs
allowingReadAccessToURL={path}
javaScriptEnabled
originWhitelist={['*']}
sharedCookiesEnabled
source={{
uri:
Platform.OS === 'ios'
? `file://${path}/index.html`
: `${path}/index.html`,
}}
injectedJavaScript={`(function () {
window.ReactNativeWebView.postMessage(JSON.stringify(document.coookie));
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url) {
this.addEventListener("load", function () {
var responseHeaders = this.getAllResponseHeaders();
var setCookies = this.getResponseHeader("Set-Cookie"); // always return null
window.ReactNativeWebView.postMessage(JSON.stringify({ setCookies }));
window.ReactNativeWebView.postMessage(
JSON.stringify({ responseHeaders }) // return all headers except for Set-Cookie
);
});
open.apply(this, arguments);
};
})();
`}
onMessage={e => {
console.log({onMessageEvent: e.nativeEvent.data});
}}
style={styles.webview}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
height: '100%',
width: '100%',
},
});
export default React.memo(Wrapper);
你知道如何解决这个问题吗?
P.S:我们已经看过如何将WKWebView cookie设置为接受策略了,但这是给斯威夫特的。
发布于 2021-10-06 20:38:26
我设法
在WebView中启用Set-Cookie行为
通过使用socket.io-client
建立套接字连接,所以WebView中的web套接字请求已经在请求头中包含cookies (这将使连接保持活动)。
考虑到react-native-webview
在iOS上使用WKWebView
,无法访问响应头中的cookie。。但是,在这个特定的场景中,您可以在web视图之外创建套接字连接,处理cookie(似乎socket.io-client
已经这样做了),然后它们应该可以在WebView中的请求中使用。
为了在您的本机应用程序中安装socket io,您需要
socket.io-client@2.1.1
(我尝试了不同的版本,但这是唯一起作用的版本)window.navigator.userAgent = 'react-native';
(由于ES6模块已被提升,此分配不能在与react-本机和socket导入相同的文件中完成)所以看起来应该是:
// userAgent.js
window.navigator.userAgent = 'react-native';
// Wrapper.tsx
import React from 'react';
import {Platform, StyleSheet, View} from 'react-native';
import {WebView} from 'react-native-webview';
// user agent MUST be imported before socket io
import './userAgent';
import io from 'socket.io-client';
export const socket = io('https://your.host.com/', {
path: '/path/to/socket.io/',
jsonp: false,
});
type WrapperProps = {
path: string;
};
function Wrapper({path}: WrapperProps) {
return (
<View style={styles.container}>
<WebView
allowFileAccess
allowUniversalAccessFromFileURLs
allowingReadAccessToURL={path}
javaScriptEnabled
originWhitelist={['*']}
sharedCookiesEnabled
source={{
uri:
Platform.OS === 'ios'
? `file://${path}/index.html`
: `${path}/index.html`,
}}
style={styles.webview}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
height: '100%',
width: '100%',
},
});
export default React.memo(Wrapper);
https://stackoverflow.com/questions/69469144
复制相似问题