JQNet.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /*
  2. This file is part of JQLibrary
  3. Copyright: Jason
  4. Contact email: 188080501@qq.com
  5. GNU Lesser General Public License Usage
  6. Alternatively, this file may be used under the terms of the GNU Lesser
  7. General Public License version 2.1 or version 3 as published by the Free
  8. Software Foundation and appearing in the file LICENSE.LGPLv21 and
  9. LICENSE.LGPLv3 included in the packaging of this file. Please review the
  10. following information to ensure the GNU Lesser General Public License
  11. requirements will be met: https://www.gnu.org/licenses/lgpl.html and
  12. http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  13. */
  14. #include "JQNet.h"
  15. // Qt lib import
  16. #include <QEventLoop>
  17. #include <QTimer>
  18. #include <QUrl>
  19. #include <QHostInfo>
  20. // JQLibrary lib import
  21. #ifdef JQFOUNDATION_LIB
  22. # include "JQFoundation.h"
  23. #endif
  24. QNetworkAddressEntry JQNet::getNetworkAddressEntry()
  25. {
  26. return getNetworkAddressEntryWithNetworkInterface().first;
  27. }
  28. QPair< QNetworkAddressEntry, QNetworkInterface > JQNet::getNetworkAddressEntryWithNetworkInterface(const bool &ridVm)
  29. {
  30. for ( const auto &interface: static_cast< const QList< QNetworkInterface > >( QNetworkInterface::allInterfaces() ) )
  31. {
  32. if ( interface.flags() != ( QNetworkInterface::IsUp |
  33. QNetworkInterface::IsRunning |
  34. QNetworkInterface::CanBroadcast |
  35. QNetworkInterface::CanMulticast ) ) { continue; }
  36. if ( ridVm && interface.humanReadableName().startsWith( "vm" ) ) { continue; }
  37. for ( const auto &entry: static_cast< QList<QNetworkAddressEntry> >( interface.addressEntries() ) )
  38. {
  39. if ( entry.ip().toIPv4Address() )
  40. {
  41. return { entry, interface };
  42. }
  43. }
  44. }
  45. return { };
  46. }
  47. QString JQNet::getHostName()
  48. {
  49. #if ( defined Q_OS_MAC )
  50. return QHostInfo::localHostName().replace( ".local", "" );
  51. #else
  52. return QHostInfo::localHostName();
  53. #endif
  54. }
  55. #ifdef JQFOUNDATION_LIB
  56. bool JQNet::pingIp(const QHostAddress &hostAddress)
  57. {
  58. // qDebug() << "NetworkManage::pingIp:" << hostAddress.toString();
  59. QPair< int, QByteArray > pingResult = { -1, { } };
  60. #ifdef Q_OS_MAC
  61. pingResult = JQFoundation::startProcessAndReadOutput( "ping", { "-c1", "-W300", hostAddress.toString() } );
  62. #endif
  63. #ifdef Q_OS_WIN
  64. pingResult = JQFoundation::startProcessAndReadOutput( "ping", { "-n", "1", "-w", "300", hostAddress.toString() } );
  65. #endif
  66. return ( pingResult.first == 0 ) && ( pingResult.second.size() > 20 ) && ( pingResult.second.count( hostAddress.toString().toUtf8() ) > 1 );
  67. }
  68. #endif
  69. // HTTP
  70. bool JQNet::HTTP::get(
  71. const QNetworkRequest &request,
  72. QByteArray &target, const int &timeout
  73. )
  74. {
  75. target.clear();
  76. QEventLoop eventLoop;
  77. auto reply = manage_.get( request );
  78. bool failFlag = false;
  79. this->handle(
  80. reply,
  81. timeout,
  82. [ & ](const QByteArray &data)
  83. {
  84. target = data;
  85. eventLoop.exit( 1 );
  86. },
  87. [ & ](const QNetworkReply::NetworkError &, const QByteArray &data)
  88. {
  89. target = data;
  90. eventLoop.exit( 0 );
  91. },
  92. [ & ]()
  93. {
  94. failFlag = true;
  95. eventLoop.exit( 0 );
  96. }
  97. );
  98. return eventLoop.exec() && !failFlag;
  99. }
  100. void JQNet::HTTP::get(
  101. const QNetworkRequest &request,
  102. const std::function<void (const QByteArray &)> &onFinished,
  103. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &)> &onError,
  104. const int &timeout
  105. )
  106. {
  107. auto reply = manage_.get( request );
  108. this->handle(
  109. reply,
  110. timeout,
  111. onFinished,
  112. onError,
  113. [ onError ]()
  114. {
  115. onError( QNetworkReply::TimeoutError, { } );
  116. }
  117. );
  118. }
  119. bool JQNet::HTTP::deleteResource(
  120. const QNetworkRequest &request,
  121. QByteArray &target,
  122. const int &timeout
  123. )
  124. {
  125. target.clear();
  126. QEventLoop eventLoop;
  127. auto reply = manage_.deleteResource( request );
  128. bool failFlag = false;
  129. this->handle(
  130. reply,
  131. timeout,
  132. [ & ](const QByteArray &data)
  133. {
  134. target = data;
  135. eventLoop.exit( 1 );
  136. },
  137. [ & ](const QNetworkReply::NetworkError &, const QByteArray &data)
  138. {
  139. target = data;
  140. eventLoop.exit( 0 );
  141. },
  142. [ & ]()
  143. {
  144. failFlag = true;
  145. eventLoop.exit( 0 );
  146. }
  147. );
  148. return eventLoop.exec() && !failFlag;
  149. }
  150. void JQNet::HTTP::deleteResource(
  151. const QNetworkRequest &request,
  152. const std::function<void (const QByteArray &)> &onFinished,
  153. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &)> &onError,
  154. const int &timeout
  155. )
  156. {
  157. auto reply = manage_.deleteResource( request );
  158. this->handle(
  159. reply,
  160. timeout,
  161. onFinished,
  162. onError,
  163. [ onError ]()
  164. {
  165. onError( QNetworkReply::TimeoutError, { } );
  166. }
  167. );
  168. }
  169. bool JQNet::HTTP::post(
  170. const QNetworkRequest &request,
  171. const QByteArray &body,
  172. QByteArray &target,
  173. const int &timeout
  174. )
  175. {
  176. target.clear();
  177. QEventLoop eventLoop;
  178. auto reply = manage_.post( request, body );
  179. bool failFlag = false;
  180. this->handle(
  181. reply,
  182. timeout,
  183. [ &target, &eventLoop ](const QByteArray &data)
  184. {
  185. target = data;
  186. eventLoop.exit( true );
  187. },
  188. [ &target, &eventLoop ](const QNetworkReply::NetworkError &, const QByteArray &data)
  189. {
  190. target = data;
  191. eventLoop.exit( false );
  192. },
  193. [ &failFlag, &eventLoop ]()
  194. {
  195. failFlag = true;
  196. eventLoop.exit( false );
  197. }
  198. );
  199. return eventLoop.exec() && !failFlag;
  200. }
  201. bool JQNet::HTTP::post(
  202. const QNetworkRequest &request,
  203. const QSharedPointer< QHttpMultiPart > &multiPart,
  204. QByteArray &target,
  205. const int &timeout
  206. )
  207. {
  208. target.clear();
  209. QEventLoop eventLoop;
  210. auto reply = manage_.post( request, multiPart.data() );
  211. bool failFlag = false;
  212. this->handle(
  213. reply,
  214. timeout,
  215. [ &target, &eventLoop ](const QByteArray &data)
  216. {
  217. target = data;
  218. eventLoop.exit( true );
  219. },
  220. [ &target, &eventLoop ](const QNetworkReply::NetworkError &, const QByteArray &data)
  221. {
  222. target = data;
  223. eventLoop.exit( false );
  224. },
  225. [ &failFlag, &eventLoop ]()
  226. {
  227. failFlag = true;
  228. eventLoop.exit( false );
  229. }
  230. );
  231. return eventLoop.exec() && !failFlag;
  232. }
  233. void JQNet::HTTP::post(
  234. const QNetworkRequest &request,
  235. const QByteArray &body,
  236. const std::function<void (const QByteArray &)> &onFinished,
  237. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &)> &onError,
  238. const int &timeout
  239. )
  240. {
  241. auto reply = manage_.post( request, body );
  242. this->handle(
  243. reply,
  244. timeout,
  245. onFinished,
  246. onError,
  247. [ onError ]()
  248. {
  249. onError( QNetworkReply::TimeoutError, { } );
  250. }
  251. );
  252. }
  253. bool JQNet::HTTP::put(
  254. const QNetworkRequest &request,
  255. const QByteArray &body,
  256. QByteArray &target,
  257. const int &timeout
  258. )
  259. {
  260. target.clear();
  261. QEventLoop eventLoop;
  262. auto reply = manage_.put( request, body );
  263. bool failFlag = false;
  264. this->handle(
  265. reply,
  266. timeout,
  267. [ &target, &eventLoop ](const QByteArray &data)
  268. {
  269. target = data;
  270. eventLoop.exit( true );
  271. },
  272. [ &target, &eventLoop ](const QNetworkReply::NetworkError &, const QByteArray &data)
  273. {
  274. target = data;
  275. eventLoop.exit( false );
  276. },
  277. [ &failFlag, &eventLoop ]()
  278. {
  279. failFlag = true;
  280. eventLoop.exit( false );
  281. }
  282. );
  283. return eventLoop.exec() && !failFlag;
  284. }
  285. bool JQNet::HTTP::put(
  286. const QNetworkRequest &request,
  287. const QSharedPointer< QHttpMultiPart > &multiPart,
  288. QByteArray &target,
  289. const int &timeout
  290. )
  291. {
  292. target.clear();
  293. QEventLoop eventLoop;
  294. auto reply = manage_.put( request, multiPart.data() );
  295. bool failFlag = false;
  296. this->handle(
  297. reply,
  298. timeout,
  299. [ &target, &eventLoop ](const QByteArray &data)
  300. {
  301. target = data;
  302. eventLoop.exit( true );
  303. },
  304. [ &target, &eventLoop ](const QNetworkReply::NetworkError &e, const QByteArray &data)
  305. {
  306. qDebug() << e;
  307. target = data;
  308. eventLoop.exit( false );
  309. },
  310. [ &failFlag, &eventLoop ]()
  311. {
  312. failFlag = true;
  313. eventLoop.exit( false );
  314. }
  315. );
  316. return eventLoop.exec() && !failFlag;
  317. }
  318. void JQNet::HTTP::put(
  319. const QNetworkRequest &request,
  320. const QByteArray &body,
  321. const std::function<void (const QByteArray &)> &onFinished,
  322. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &)> &onError,
  323. const int &timeout
  324. )
  325. {
  326. auto reply = manage_.put( request, body );
  327. this->handle(
  328. reply,
  329. timeout,
  330. onFinished,
  331. onError,
  332. [ onError ]()
  333. {
  334. onError( QNetworkReply::TimeoutError, { } );
  335. }
  336. );
  337. }
  338. #if !( defined Q_OS_LINUX ) && ( QT_VERSION >= QT_VERSION_CHECK( 5, 9, 0 ) )
  339. bool JQNet::HTTP::patch(
  340. const QNetworkRequest &request,
  341. const QByteArray &body,
  342. QByteArray &target,
  343. const int &timeout
  344. )
  345. {
  346. target.clear();
  347. QEventLoop eventLoop;
  348. auto reply = manage_.sendCustomRequest( request, "PATCH", body );
  349. bool failFlag = false;
  350. this->handle(
  351. reply,
  352. timeout,
  353. [ &target, &eventLoop ](const QByteArray &data)
  354. {
  355. target = data;
  356. eventLoop.exit( true );
  357. },
  358. [ &target, &eventLoop ](const QNetworkReply::NetworkError &, const QByteArray &data)
  359. {
  360. target = data;
  361. eventLoop.exit( false );
  362. },
  363. [ &failFlag, &eventLoop ]()
  364. {
  365. failFlag = true;
  366. eventLoop.exit( false );
  367. }
  368. );
  369. return eventLoop.exec() && !failFlag;
  370. }
  371. void JQNet::HTTP::patch(
  372. const QNetworkRequest &request,
  373. const QByteArray &body,
  374. const std::function<void (const QByteArray &)> &onFinished,
  375. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &)> &onError,
  376. const int &timeout
  377. )
  378. {
  379. auto reply = manage_.sendCustomRequest( request, "PATCH", body );
  380. this->handle(
  381. reply,
  382. timeout,
  383. onFinished,
  384. onError,
  385. [ onError ]()
  386. {
  387. onError( QNetworkReply::TimeoutError, { } );
  388. }
  389. );
  390. }
  391. #endif
  392. QPair< bool, QByteArray > JQNet::HTTP::get(const QString &url, const int &timeout)
  393. {
  394. QNetworkRequest networkRequest( ( QUrl( url ) ) );
  395. QByteArray buf;
  396. const auto &&flag = HTTP().get( networkRequest, buf, timeout );
  397. return { flag, buf };
  398. }
  399. QPair< bool, QByteArray > JQNet::HTTP::get(const QNetworkRequest &request, const int &timeout)
  400. {
  401. QByteArray buf;
  402. HTTP http;
  403. const auto &&flag = http.get( request, buf, timeout );
  404. return { flag, buf };
  405. }
  406. QPair< bool, QByteArray > JQNet::HTTP::deleteResource(const QString &url, const int &timeout)
  407. {
  408. QNetworkRequest networkRequest( ( QUrl( url ) ) );
  409. QByteArray buf;
  410. const auto &&flag = HTTP().deleteResource( networkRequest, buf, timeout );
  411. return { flag, buf };
  412. }
  413. QPair< bool, QByteArray > JQNet::HTTP::deleteResource(const QNetworkRequest &request, const int &timeout)
  414. {
  415. QByteArray buf;
  416. HTTP http;
  417. const auto &&flag = http.deleteResource( request, buf, timeout );
  418. return { flag, buf };
  419. }
  420. QPair< bool, QByteArray > JQNet::HTTP::post(const QString &url, const QByteArray &body, const int &timeout)
  421. {
  422. QNetworkRequest networkRequest( ( QUrl( url ) ) );
  423. QByteArray buf;
  424. networkRequest.setRawHeader( "Content-Type", "application/x-www-form-urlencoded" );
  425. const auto &&flag = HTTP().post( networkRequest, body, buf, timeout );
  426. return { flag, buf };
  427. }
  428. QPair< bool, QByteArray > JQNet::HTTP::post(const QNetworkRequest &request, const QByteArray &body, const int &timeout)
  429. {
  430. QByteArray buf;
  431. HTTP http;
  432. const auto &&flag = http.post( request, body, buf, timeout );
  433. return { flag, buf };
  434. }
  435. QPair< bool, QByteArray > JQNet::HTTP::post(const QNetworkRequest &request, const QSharedPointer<QHttpMultiPart> &multiPart, const int &timeout)
  436. {
  437. QByteArray buf;
  438. HTTP http;
  439. const auto &&flag = http.post( request, multiPart, buf, timeout );
  440. return { flag, buf };
  441. }
  442. QPair< bool, QByteArray > JQNet::HTTP::put(const QString &url, const QByteArray &body, const int &timeout)
  443. {
  444. QNetworkRequest networkRequest( ( QUrl( url ) ) );
  445. QByteArray buf;
  446. networkRequest.setRawHeader( "Content-Type", "application/x-www-form-urlencoded" );
  447. const auto &&flag = HTTP().put( networkRequest, body, buf, timeout );
  448. return { flag, buf };
  449. }
  450. QPair< bool, QByteArray > JQNet::HTTP::put(const QNetworkRequest &request, const QByteArray &body, const int &timeout)
  451. {
  452. QByteArray buf;
  453. HTTP http;
  454. const auto &&flag = http.put( request, body, buf, timeout );
  455. return { flag, buf };
  456. }
  457. QPair< bool, QByteArray > JQNet::HTTP::put(const QNetworkRequest &request, const QSharedPointer< QHttpMultiPart > &multiPart, const int &timeout)
  458. {
  459. QByteArray buf;
  460. HTTP http;
  461. const auto &&flag = http.put( request, multiPart, buf, timeout );
  462. return { flag, buf };
  463. }
  464. #if !( defined Q_OS_LINUX ) && ( QT_VERSION >= QT_VERSION_CHECK( 5, 9, 0 ) )
  465. QPair< bool, QByteArray > JQNet::HTTP::patch(const QString &url, const QByteArray &body, const int &timeout)
  466. {
  467. QNetworkRequest networkRequest( ( QUrl( url ) ) );
  468. QByteArray buf;
  469. networkRequest.setRawHeader( "Content-Type", "application/x-www-form-urlencoded" );
  470. const auto &&flag = HTTP().patch( networkRequest, body, buf, timeout );
  471. return { flag, buf };
  472. }
  473. QPair< bool, QByteArray > JQNet::HTTP::patch(const QNetworkRequest &request, const QByteArray &body, const int &timeout)
  474. {
  475. QByteArray buf;
  476. HTTP http;
  477. const auto &&flag = http.patch( request, body, buf, timeout );
  478. return { flag, buf };
  479. }
  480. #endif
  481. void JQNet::HTTP::handle(
  482. QNetworkReply *reply, const int &timeout,
  483. const std::function<void (const QByteArray &)> &onFinished,
  484. const std::function<void (const QNetworkReply::NetworkError &, const QByteArray &data)> &onError,
  485. const std::function<void ()> &onTimeout
  486. )
  487. {
  488. QSharedPointer< bool > isCalled( new bool( false ) );
  489. QTimer *timer = nullptr;
  490. if ( timeout )
  491. {
  492. timer = new QTimer;
  493. timer->setSingleShot(true);
  494. QObject::connect( timer, &QTimer::timeout, [ timer, onTimeout, isCalled ]()
  495. {
  496. if ( *isCalled ) { return; }
  497. *isCalled = true;
  498. onTimeout();
  499. timer->deleteLater();
  500. } );
  501. timer->start( timeout );
  502. }
  503. QObject::connect( reply, &QNetworkReply::finished, [ reply, timer, onFinished, isCalled ]()
  504. {
  505. if ( *isCalled ) { return; }
  506. *isCalled = true;
  507. if ( timer )
  508. {
  509. timer->deleteLater();
  510. }
  511. const auto &&acceptedData = reply->readAll();
  512. // qDebug() << acceptedData;
  513. onFinished( acceptedData );
  514. } );
  515. #ifndef QT_NO_SSL
  516. if ( reply->url().toString().toLower().startsWith( "https" ) )
  517. {
  518. QObject::connect( reply, static_cast< void( QNetworkReply::* )( const QList< QSslError > & ) >( &QNetworkReply::sslErrors ), [ reply ](const QList< QSslError > &errors)
  519. {
  520. qDebug() << "HTTP::handle: ignoreSslErrors:" << errors;
  521. reply->ignoreSslErrors();
  522. } );
  523. }
  524. #endif
  525. QObject::connect( reply, static_cast< void( QNetworkReply::* )( QNetworkReply::NetworkError ) >( &QNetworkReply::error ), [ reply, timer, onError, isCalled ](const QNetworkReply::NetworkError &code)
  526. {
  527. if ( *isCalled ) { return; }
  528. *isCalled = true;
  529. if ( timer )
  530. {
  531. timer->deleteLater();
  532. }
  533. const auto &&acceptedData = reply->readAll();
  534. // qDebug() << acceptedData;
  535. onError( code, acceptedData );
  536. } );
  537. }