[セットトップ]react nativeはfetchを使ってネットワーク要求(https)を行い、SSLHandschake問題を解決し、どのように二次パッキングを行いますか?
21307 ワード
react nativeはfetchを使ってネットワーク要求を行う(https問題SSLHandschake、解決方法)使用例 カプセル化はどのように行いますか? よくある問題(タイムアウト設定、無効なssl証明書、…) fetchの原理解説 インスタンスを使う
1.get方式を用いたネットワーク要求、例えば:
基本的に要求されるのは基本的な関数です.他のネットワーク要求時にはこの関数を呼び出します.今後はfetchを使わずにこの基礎関数を直接修正しても、他のところを修正しなくても実現できます.
基本関数のモデルは一般的にこのようです.
よくある問題
1.要求時に異常が発生する
headerの中のContentt-Typeを'appication/x-wn-form-urlencoded'に設定します.もしまだserver端パラメータがどんなフォーマットなのかを聞き間違えたら、Content-Typeの値を設定すればいいです.
2.応答時に異常が発生する
上記のパッケージは簡単に問題が発生します.この文の中で、レスポンス==nullが異常を出すと、まずレスポンスがnullかどうかを判断し、nullの場合は特殊処理を行うことをお勧めします.
3.fetch設定のタイムアウト時間
fetch自体は現在タイムアウト時間の属性が設定されていませんので、設定するしかありません.fetch関数は各プラットフォームで実装されています.ソースコードを見たら、タイムアウトを設定するのは簡単だと思いますが、カプセル化時にはこれを一つの属性として設定していません.したがって、promiseメカニズムに合わせてsetTimeoutを使用してタイムアウトの時間を設定するしかないです.
4.https、server端が無効証明書でhttps要求した時に発生したエラー
SSLHandschake:Received fatal alert:certificate_expiredまたはSSLHandschake:Remote host closed connection during hadshak…
(1)Androidでは、httpしか使えません.ライブラリの中の関数は変えられません.httpsをサポートしなければならないなら、あなたのプロジェクトのカタログを+node_modules/react-native/android/com/facebook/react-native/0.6.0/react-native-06.0-sources.jar!/com/facebook/react/modules/network/OkHttp ClientProvider.java、
他のrnバージョンのファイルディレクトリは、総じてreactnativeのnetworkライブラリ内のOkHttpClientProvider.javaというファイルを修正したと推測できます.
OkHttp ClientProvider.javaの中で下記のコードを見つけました.
原理解説、各プラットフォームでfetch実現のカギコード
react nativeのネットワーク操作はよく使われるfetchであり、fetch関数の実現はiOSとandroidプラットフォームでそれぞれRCTNetworkingを使用して実現されることがわかった.上記の4つ目の問題の解決は、RCTNetworkingソースコードを見ることによって解決されます.
android上のキーコード分析:
以下は実現されるRCT Networkingです.よく見るとOkHttpClientで実現されます.
ios端キーコード説明
RCT NetInfoクラスで実現される機能:ネットワークがWiFiかどうかを問い合わせる.RCT Networking類で実現される機能:AFNetworkingの実現と同じです.よく検討してください.とりあえず
最後に完全なインスタンスを提供します.
1.新規プロジェクト:
実行コマンドreact-native init ZXJNetDemo
2.コードの作成
新規ファイルBaserviceApple Net.js:
1.get方式を用いたネットワーク要求、例えば:
fetch('http://nero-zou.com/test', {
method: 'GET'
}).then(function(response) {
// ,
}).catch(function(err) {
//
});
2.post方式を使用してネットワーク要求、例えば:let param = {user:'xxx',phone:'xxxxxx'};
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
// ,
});
3.他の書き方、例えば:try {
fetch(url, {
method: 'post',
body: JSON.stringify(param)
}).then(function(response) {
// ,
});
} catch(e) {
//
}
4.headerまたは他のパラメータを持つfetch(url, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', },
body: JSON.stringify({ firstParam: 'yourValue', secondParam: 'yourOtherValue', })
})
パッケージはどうしますか基本的に要求されるのは基本的な関数です.他のネットワーク要求時にはこの関数を呼び出します.今後はfetchを使わずにこの基礎関数を直接修正しても、他のところを修正しなくても実現できます.
基本関数のモデルは一般的にこのようです.
function sendNetRequest(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
return fetch(this.url, Object.assign({}, this.options))
.then((response) =>return response.json());
}
各インターフェースを実装 // login
function postLogin(userName,password) {
let loginParam= {user:userName,password:password};
var loginApiPort = "mlogin";//login
// baseURL=https://XXXXX.com
return sendNetRequest(`${baseURL}/${loginApiPort}`, {
method: 'post',
body: JSON.stringify(loginParam),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
}
//...
呼び出しのインスタンス try {
postLogin(user,password)
.then((response) => { // , }) } catch(e) { // }
これで成功しました.次はよくある問題です.よくある問題
1.要求時に異常が発生する
headerの中のContentt-Typeを'appication/x-wn-form-urlencoded'に設定します.もしまだserver端パラメータがどんなフォーマットなのかを聞き間違えたら、Content-Typeの値を設定すればいいです.
2.応答時に異常が発生する
上記のパッケージは簡単に問題が発生します.この文の中で、レスポンス==nullが異常を出すと、まずレスポンスがnullかどうかを判断し、nullの場合は特殊処理を行うことをお勧めします.
3.fetch設定のタイムアウト時間
fetch自体は現在タイムアウト時間の属性が設定されていませんので、設定するしかありません.fetch関数は各プラットフォームで実装されています.ソースコードを見たら、タイムアウトを設定するのは簡単だと思いますが、カプセル化時にはこれを一つの属性として設定していません.したがって、promiseメカニズムに合わせてsetTimeoutを使用してタイムアウトの時間を設定するしかないです.
4.https、server端が無効証明書でhttps要求した時に発生したエラー
SSLHandschake:Received fatal alert:certificate_expiredまたはSSLHandschake:Remote host closed connection during hadshak…
(1)Androidでは、httpしか使えません.ライブラリの中の関数は変えられません.httpsをサポートしなければならないなら、あなたのプロジェクトのカタログを+node_modules/react-native/android/com/facebook/react-native/0.6.0/react-native-06.0-sources.jar!/com/facebook/react/modules/network/OkHttp ClientProvider.java、
他のrnバージョンのファイルディレクトリは、総じてreactnativeのnetworkライブラリ内のOkHttpClientProvider.javaというファイルを修正したと推測できます.
OkHttp ClientProvider.javaの中で下記のコードを見つけました.
return new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
変更: return new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true; // , true
}
})
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
2.iOS端、xcodeでiosディレクトリ下のプロジェクトを開け、infor.plistを見つけ、属性を追加する. <key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
やはりエラーです.React nativeのnetworkingライブラリを見つけて、倉庫にNSURLSession delegate関数を追加してssl証明書認証の関連コードを処理して、全部パスに設定します.debugモードかどうかによってパスかどうかを選択してもいいです.release版であれば、やめてください.この関数のように// , pass, , pass http 。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
5.忘れました.画像をアップロードする時に発生した問題のようです.後で追加します.原理解説、各プラットフォームでfetch実現のカギコード
react nativeのネットワーク操作はよく使われるfetchであり、fetch関数の実現はiOSとandroidプラットフォームでそれぞれRCTNetworkingを使用して実現されることがわかった.上記の4つ目の問題の解決は、RCTNetworkingソースコードを見ることによって解決されます.
android上のキーコード分析:
以下は実現されるRCT Networkingです.よく見るとOkHttpClientで実現されます.
@ReactModule(name = "RCTNetworking", supportsWebWorkers = true)
public final class NetworkingModule extends ReactContextBaseJavaModule {
private static final String CONTENT_ENCODING_HEADER_NAME = "content-encoding";
private static final String CONTENT_TYPE_HEADER_NAME = "content-type";
private static final String REQUEST_BODY_KEY_STRING = "string";
private static final String REQUEST_BODY_KEY_URI = "uri";
private static final String REQUEST_BODY_KEY_FORMDATA = "formData";
private static final String USER_AGENT_HEADER_NAME = "user-agent";
private static final int CHUNK_TIMEOUT_NS = 100 * 1000000; // 100ms
private static final int MAX_CHUNK_SIZE_BETWEEN_FLUSHES = 8 * 1024; // 8K
private final OkHttpClient mClient;// OkHttpClient
private final ForwardingCookieHandler mCookieHandler;
private final @Nullable String mDefaultUserAgent;
private final CookieJarContainer mCookieJarContainer;
private final Set<Integer> mRequestIds;
private boolean mShuttingDown;
/* package */ NetworkingModule(
ReactApplicationContext reactContext,
@Nullable String defaultUserAgent,
OkHttpClient client,
@Nullable List<NetworkInterceptorCreator> networkInterceptorCreators) {
super(reactContext);
if (networkInterceptorCreators != null) {
OkHttpClient.Builder clientBuilder = client.newBuilder();
for (NetworkInterceptorCreator networkInterceptorCreator : networkInterceptorCreators) {
clientBuilder.addNetworkInterceptor(networkInterceptorCreator.create());
}
client = clientBuilder.build();
}
mClient = client;
OkHttpClientProvider.replaceOkHttpClient(client);
mCookieHandler = new ForwardingCookieHandler(reactContext);
mCookieJarContainer = (CookieJarContainer) mClient.cookieJar();
mShuttingDown = false;
mDefaultUserAgent = defaultUserAgent;
mRequestIds = new HashSet<>();
}
OkHttp ClidentProviderは、ネットワーク要求を管理するために、単一のインスタンスクラスを作成します.public class OkHttpClientProvider {
// Centralized OkHttpClient for all networking requests.
private static @Nullable OkHttpClient sClient;
public static OkHttpClient getOkHttpClient() {
if (sClient == null) {
//sClient = createClient();
sClient=createClient_initNetworkConfig();
}
return sClient;
}
// okhttp3 OkHttpClient is immutable
// This allows app to init an OkHttpClient with custom settings.
public static void replaceOkHttpClient(OkHttpClient client) {
sClient = client;
}
private static OkHttpClient createClient() {
// No timeouts by default
return new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS)
.cookieJar(new ReactCookieJarContainer())
.build();
}
上記のコードによりタイムアウトは設定できますが、fetchはこの属性を実装していません.ios端キーコード説明
RCT NetInfoクラスで実現される機能:ネットワークがWiFiかどうかを問い合わせる.RCT Networking類で実現される機能:AFNetworkingの実現と同じです.よく検討してください.とりあえず
最後に完全なインスタンスを提供します.
1.新規プロジェクト:
実行コマンドreact-native init ZXJNetDemo
2.コードの作成
新規ファイルBaserviceApple Net.js:
const baseURL = "https://api.app.net";
function fetchAction(...props) {
this.url = props.shift(1);
this.options = props.shift(1);
return fetch(this.url, Object.assign({}, this.options))
.then((response) =>response.json());
}
export default {
getTest() {
var apiPort = "stream/0/posts/stream/global";
return fetchAction(`${baseURL}/${apiPort}`, {
method: 'get',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
}
};
ファイルindex.ios.jsimport React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
ActivityIndicator
} from 'react-native';
import BaseServiceApiNet from './BaseServiceApiNet';
export default class ZXJNetDemo extends Component {
constructor(props){
super(props);
this.state ={
isLoading:false,
resultJson:null
};
}
sendTestRequest(){
if(this.state.isLoading==true){
return;
}
this.setState({
resultJson:null,
isLoading:true
});
try {
BaseServiceApiNet.getTest()
.then((response) => { let data = response.meta; this.setState({ resultJson:data==null?null:JSON.stringify(data), isLoading:false }); console.log(" :"+JSON.stringify(data)); }) } catch(e) { alert(e); this.setState({ isLoading:false }); } } render() { return ( <View style={styles.container}> <ActivityIndicator animating={this.state.isLoading} /> <Text style={styles.welcome} onPress={this.sendTestRequest.bind(this)}> </Text> <Text style={styles.instructions}> {this.state.resultJson} </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, }); AppRegistry.registerComponent('ZXJNetDemo', () => ZXJNetDemo);
3.運転結果: