1. 程式人生 > >基於libcurl實現REST風格http/https的get和post

基於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

/********************************************************
Copyright (C),  2016-2018,
FileName:		Get
Author:        	woniu201
Email:         	[email protected]
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

/********************************************************
Copyright (C),  2016-2018,
FileName:		Post
Author:        	woniu201
Email:         	[email protected]
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

/********************************************************
Copyright (C),  2016-2018,
FileName:		utils
Author:        	woniu201
Email:         	[email protected]
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

#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

對應libcurl庫和標頭檔案下載地址(支援HTTPS):點選下載

歡迎加群交流:C/C++開發交流

                                                         

                                                     更多技術文章掃碼關注微信公眾號