基于libcurl实现REST风格http/https的get和post

c/c++开发中经常要用到http/https协议,直接使用socket工作量很大,要是使用socket实现https,那更不可思议,开源的c/c++的http客户端框架,libcurl是首选,而且也相当成熟稳定,最近C++项目中用到https请求,就做下研究。

一:libcurl简介(来源官网)

libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。官网地址:https://curl.haxx.se/libcurl/

二:实现HTTP/GET

Get.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/********************************************************
Copyright (C), 2016-2018,
FileName: Get
Author: woniu201
Email: wangpengfei.201@163.com
Created: 2018/10/15
Description: 实现HTTP/HTTPS GET请求
********************************************************/
#include "main.h"

size_t WriteGetResp(void *buffer, size_t size, size_t nmemb, void *userp)
{
((string*)userp)->append((char*)buffer, 0, size*nmemb);
return size*nmemb;
}

/************************************
@ Brief: GET请求
@ Author: woniu201
@ Created: 2018/10/15
@ Return:
************************************/
int HttpGet(char* url)
{
string respData;
CURL* curl;
CURLcode res;

curl = curl_easy_init();
if (curl == NULL)
{
return 1;
}

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteGetResp);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &respData);

// curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 5000); //libcurl存在毫秒超时bug,如果设备小于1000ms立即返回失败
// curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000); //设置超时时间

bool bCA = FALSE;
if (!bCA)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);//设定为不验证证书和HOST
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, FALSE);
}
else
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_easy_setopt(curl, CURLOPT_CAINFO, "");
}

res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
cout << curl_easy_strerror(res) << endl;
}

curl_easy_cleanup(curl);

cout << Utf8ToAscii(respData) << endl;
return 0;
}

三:实现HTTP/POST

Post.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/********************************************************
Copyright (C), 2016-2018,
FileName: Post
Author: woniu201
Email: wangpengfei.201@163.com
Created: 2018/10/15
Description: 实现HTTP/HTTPS POST请求
********************************************************/
#include "main.h"

size_t WritePostBodyResp(void *buffer, size_t size, size_t nmemb, void *userp)
{
((string*)userp)->append((char*)buffer, 0, size*nmemb);
return size*nmemb;
}

size_t WritePostHeaderResp(void *buffer, size_t size, size_t nmemb, void *userp)
{
((string*)userp)->append((char*)buffer, 0, size*nmemb);
return size*nmemb;
}

/************************************
@ Brief: POST请求
@ Author: woniu201
@ Created: 2018/10/15
@ Return:
************************************/
int HttpPost(char* url, char* body)
{
string respBodyData;
string respHeadData;
CURL* curl;
CURLcode res;

//设置头
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");

curl = curl_easy_init();
if (curl == NULL)
{
return 1;
}

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, WritePostHeaderResp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WritePostBodyResp);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, &respHeadData);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &respBodyData);

// curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 5000); //libcurl存在毫秒超时bug,如果设备小于1000ms立即返回失败
// curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 5000); //设置超时时间

bool bCA = FALSE;
if (!bCA)
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);//设定为不验证证书和HOST
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, FALSE);
}
else
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_easy_setopt(curl, CURLOPT_CAINFO, "");
}

res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
cout << curl_easy_strerror(res) << endl;
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);

cout << Utf8ToAscii(respHeadData) << endl;
cout << Utf8ToAscii(respBodyData) << endl;

return 0;
}

其他代码

Utils.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/********************************************************
Copyright (C), 2016-2018,
FileName: utils
Author: woniu201
Email: wangpengfei.201@163.com
Created: 2018/10/15
Description: ASSIC--UTF8互转
********************************************************/
#include "main.h"
#include <string>
#include <Windows.h>
#include <wchar.h>
using namespace std;

wstring AsciiToUnicode(const string& str) {
// 预算-缓冲区中宽字节的长度
int unicodeLen = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0);
// 给指向缓冲区的指针变量分配内存
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
// 开始向缓冲区转换字节
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, pUnicode, unicodeLen);
wstring ret_str = pUnicode;
free(pUnicode);
return ret_str;
}
string UnicodeToAscii(const wstring& wstr) {
// 预算-缓冲区中多字节的长度
int ansiiLen = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
// 给指向缓冲区的指针变量分配内存
char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);
// 开始向缓冲区转换字节
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);
string ret_str = pAssii;
free(pAssii);
return ret_str;
}

wstring Utf8ToUnicode(const string& str) {
// 预算-缓冲区中宽字节的长度
int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
// 给指向缓冲区的指针变量分配内存
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
// 开始向缓冲区转换字节
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, pUnicode, unicodeLen);
wstring ret_str = pUnicode;
free(pUnicode);
return ret_str;
}
string UnicodeToUtf8(const wstring& wstr) {
// 预算-缓冲区中多字节的长度
int ansiiLen = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
// 给指向缓冲区的指针变量分配内存
char *pAssii = (char*)malloc(sizeof(char)*ansiiLen);
// 开始向缓冲区转换字节
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, pAssii, ansiiLen, nullptr, nullptr);
string ret_str = pAssii;
free(pAssii);
return ret_str;
}

/************************************
@ Brief: ASSIC转UTF8
@ Author: woniu201
@ Created: 2018/10/16
@ Return:
************************************/
string AsciiToUtf8(const string& str) {
return UnicodeToUtf8(AsciiToUnicode(str));
}

/************************************
@ Brief: UTF8转ASSIC
@ Author: woniu201
@ Created: 2018/10/16
@ Return:
************************************/
string Utf8ToAscii(const string& str) {
return UnicodeToAscii(Utf8ToUnicode(str));
}

main.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef _MAIN_H
#define _MAIN_H

#include <iostream>
#include <string>
#include "include/curl.h"

using namespace std;


#pragma comment(lib, "ssleay32.lib")
#pragma comment(lib, "libcurl.lib")

string AsciiToUtf8(const string& str);
string Utf8ToAscii(const string& str);

int HttpGet(char* url);
int HttpPost(char* url, char* body);
int HttpDownload(char* url, char* filePath);
#endif

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×