RestfulFuncImpl.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "RestfulFunc.h"
  2. #include <cpprest/http_client.h>
  3. #if defined(_MSC_VER)
  4. #include <Windows.h>
  5. #endif //_MSC_VER
  6. using namespace utility; // Common utilities like string conversions
  7. using namespace web; // Common features like URIs.
  8. using namespace web::http; // Common HTTP functionality
  9. using namespace web::http::client; // HTTP client features
  10. namespace
  11. {
  12. #if defined(_MSC_VER)
  13. static std::wstring s2w(const std::string str)
  14. {
  15. wchar_t* wstr = NULL;
  16. int n = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
  17. if (n > 0) {
  18. wstr = new wchar_t[n + 1];
  19. if (wstr == NULL) {
  20. return std::wstring();
  21. }
  22. std::memset(wstr, 0, (n + 1) * sizeof(wchar_t));
  23. ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &wstr[0], n);
  24. std::wstring strr(wstr);
  25. delete wstr;
  26. return strr;
  27. }
  28. return std::wstring();
  29. }
  30. #endif //_MSC_VER
  31. std::string w2s(const std::wstring wstr)
  32. {
  33. #if defined(_MSC_VER)
  34. char* str = NULL;
  35. int n = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
  36. if (n > 0) {
  37. str = new char[n + 1];
  38. if (str == NULL) {
  39. return std::string();
  40. }
  41. std::memset(str, 0, sizeof(char) * (n + 1));
  42. ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], n, NULL, NULL);
  43. std::string strr(str);
  44. delete str;
  45. return strr;
  46. }
  47. return std::string();
  48. #else
  49. if (wstr.empty()) {
  50. return "";
  51. }
  52. unsigned len = wcstombs(NULL, wstr.c_str(), 0) + 1;
  53. if (NULL == setlocale(LC_ALL, "zh_CN.gbk")) {
  54. }
  55. char* p = new char[len];
  56. wcstombs(p, wstr.c_str(), len);
  57. p[len - 1] = '\0';
  58. std::string str(p);
  59. delete[] p;
  60. return str;
  61. #endif // _MSC_VER
  62. }
  63. }
  64. #if defined(_MSC_VER)
  65. #define STRW(str) s2w(str)
  66. #define WSTR(str) w2s(str)
  67. #else
  68. #define STRW(str) (str)
  69. #define WSTR(str) (str)
  70. #endif //_MSC_VER
  71. RestfulClient& RestfulClient::getInstance()
  72. {
  73. static RestfulClient c;
  74. return c;
  75. }
  76. RestfulClient::RestfulClient()
  77. {
  78. }
  79. RestfulClient::~RestfulClient()
  80. {
  81. }
  82. namespace
  83. {
  84. const http::method MappingHttpRequestMethod(HttpRequestMethod provideMethod)
  85. {
  86. switch (provideMethod) {
  87. case GET:
  88. return http::methods::GET;
  89. break;
  90. case POST:
  91. return http::methods::POST;
  92. break;
  93. case PUT:
  94. return http::methods::PUT;
  95. break;
  96. case DEL:
  97. return http::methods::DEL;
  98. break;
  99. case HEAD:
  100. return http::methods::HEAD;
  101. break;
  102. case OPTIONS:
  103. return http::methods::OPTIONS;
  104. break;
  105. case TRCE:
  106. return http::methods::TRCE;
  107. break;
  108. case CONNECT:
  109. return http::methods::CONNECT;
  110. break;
  111. case MERGE:
  112. return http::methods::MERGE;
  113. break;
  114. case PATCH:
  115. return http::methods::PATCH;
  116. break;
  117. case UPLOAD:
  118. return http::methods::POST;
  119. break;
  120. case DOWNLOAD:
  121. return http::methods::POST;
  122. break;
  123. default:
  124. break;
  125. }
  126. return http::methods::GET;
  127. }
  128. void GetFileNameAndType(const std::string& absoluteFilePath, std::string& fileName, std::string& contentType)
  129. {
  130. size_t pos = absoluteFilePath.find_last_of("/\\");
  131. fileName = absoluteFilePath.substr(pos + 1);
  132. contentType = "application/octet-stream";
  133. pos = fileName.find_last_of(".");
  134. if (pos != std::string::npos) {
  135. std::string ext = fileName.substr(pos + 1);
  136. std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
  137. if (ext == "jpg" || ext == "jpeg") {
  138. contentType = "image/jpeg";
  139. } else if (ext == "txt" /*|| ext == "log"*/) {
  140. contentType = "text/plain";
  141. }
  142. }
  143. }
  144. }
  145. void RestfulClient::Do(const HttpClientRequestConfig* const pRequestConfig, HttpClientResponseResult* pResponse) const
  146. {
  147. http_client_config config;
  148. config.set_validate_certificates(pRequestConfig->NeedValidCert());
  149. const uint32_t timeoutVal = pRequestConfig->GetTimeout();
  150. if (timeoutVal != 0) {
  151. config.set_timeout(utility::seconds(timeoutVal));
  152. }
  153. web::http::client::http_client client(STRW(pRequestConfig->GetBaseUri()), config);
  154. http_request request(MappingHttpRequestMethod(pRequestConfig->GetRequestType()));
  155. uri_builder urib(STRW(pRequestConfig->GetSubUri()));
  156. if (pRequestConfig->GetQueryPairs().size() > 0) {
  157. const auto& queries = pRequestConfig->GetQueryPairs();
  158. for (auto it = queries.cbegin(); it != queries.cend(); ++it) {
  159. urib.append_query(STRW(it->first), STRW(it->second));
  160. }
  161. }
  162. request.set_request_uri(urib.to_string());
  163. request.headers().add(header_names::accept, STRW(pRequestConfig->GetAcceptType()));
  164. std::string token, channelId, terminalno, reserve1;
  165. if (pRequestConfig->getToken(channelId, token, terminalno, reserve1))
  166. {
  167. request.headers().add(STRW("channelId"), STRW(channelId));
  168. request.headers().add(STRW("token"), STRW(token));
  169. request.headers().add(STRW("terminalno"), STRW(terminalno));
  170. }
  171. if (pRequestConfig->GetRequestType() != HttpRequestMethod::GET) {
  172. request.set_body(STRW(pRequestConfig->GetBodyContent()), STRW(pRequestConfig->GetContentType()));
  173. }
  174. if (pRequestConfig->GetRequestType() == HttpRequestMethod::DOWNLOAD) {
  175. pplx::task<void> requestTask = client.request(request)
  176. .then([pResponse](http_response response) ->pplx::task<utility::string_t> {
  177. pResponse->statusCode = response.status_code();
  178. if (pResponse->ResponseOK()) {
  179. return response.extract_string();
  180. } else {
  181. std::cout << "response status result: " << response.status_code() << std::endl;
  182. return pplx::task_from_result(utility::string_t());
  183. }
  184. })
  185. .then([pResponse](pplx::task<utility::string_t> vt) {
  186. try {
  187. pResponse->content = WSTR(vt.get());
  188. } catch (const http_exception& ex) {
  189. pResponse->statusCode = -1;
  190. pResponse->content = ex.what();
  191. }
  192. });
  193. try {
  194. requestTask.wait();
  195. } catch (const std::exception& ex) {
  196. pResponse->statusCode = -1;
  197. pResponse->content = ex.what();
  198. }
  199. } else {
  200. pplx::task<void> requestTask = client.request(request)
  201. .then([pResponse](http_response response) ->pplx::task<json::value> {
  202. pResponse->statusCode = response.status_code();
  203. if (pResponse->ResponseOK()) {
  204. return response.extract_json();
  205. } else {
  206. std::cout << "response status result: " << response.status_code() << std::endl;
  207. return pplx::task_from_result(json::value());
  208. }
  209. })
  210. .then([pResponse](pplx::task<json::value> vt) {
  211. try {
  212. json::value const& v = vt.get();
  213. pResponse->content = WSTR(v.to_string());
  214. } catch (const http_exception& ex) {
  215. pResponse->statusCode = -1;
  216. pResponse->content = ex.what();
  217. }
  218. });
  219. try {
  220. requestTask.wait();
  221. } catch (const std::exception& ex) {
  222. pResponse->statusCode = -1;
  223. pResponse->content = ex.what();
  224. }
  225. }
  226. }
  227. std::pair<std::string, std::string> HttpClientUploadRequest::BuildBodyContent() const
  228. {
  229. std::stringstream data;
  230. std::string boundary{};
  231. for (int i = 0; i < 50; i++) {
  232. boundary += (rand() % 26) + 'A';
  233. }
  234. for (auto& param : mParams) {
  235. data << "\r\n--";
  236. data << boundary;
  237. data << "\r\nContent-Disposition: form-data; name=\"";
  238. data << param.first;
  239. data << "\"\r\n\r\n";
  240. data << param.second;
  241. }
  242. for (auto& file : mFiles) {
  243. std::string inputFileName;
  244. std::string contentType;
  245. GetFileNameAndType(file.second, inputFileName, contentType);
  246. std::ifstream inputFile;
  247. inputFile.open(file.second, std::ios::binary | std::ios::in);
  248. std::string inputFileContent = std::string((std::istreambuf_iterator<char>(inputFile)), (std::istreambuf_iterator<char>()));
  249. data << "\r\n--";
  250. data << boundary;
  251. data << "\r\nContent-Disposition: form-data; name=\"";
  252. data << file.first;
  253. data << "\"; filename=\"";
  254. data << inputFileName;
  255. data << "\"\r\nContent-Type: ";
  256. data << contentType;
  257. data << "\r\n\r\n";
  258. data << inputFileContent;
  259. }
  260. data << "\r\n--";
  261. data << boundary;
  262. data << "--\r\n";
  263. return { boundary, data.str() };
  264. }