본문 바로가기
IT/programming

[C/C++] C++ curl handler class 예제, C언어 curl 구현

by 어느해겨울 2022. 1. 13.

C++ curl handler class 예제

C언어 curl, C++ curl, libcurl, linux curl


C++ 클래스로 curl 을 쉽게 사용하게끔 구현하여 공유한다.

혹시 C에서 사용하고 싶다면 해당 소스코드의 클래스 내에 libcurl 함수를 제어하는 부분만 뽑아서 사용하길 바란다.

 

https://github.com/muabow/home/tree/main/library/cpp/api_curl

 

GitHub - muabow/home: C/C++, PHP, GO source/library

C/C++, PHP, GO source/library. Contribute to muabow/home development by creating an account on GitHub.

github.com

 

목차

1. 소스코드 : include/api_curl.h

2. 소스코드 : src/api_curl.cpp

3. 소스코드 : sample.cpp

4. 컴파일 및 실행 결과

 


1. 소스코드 : include/api_curl.h

#ifndef __API_CURL_H__
#define __API_CURL_H__

#include <stdarg.h>

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

using namespace std;

class CURL_Handler {
	private :
		bool			is_debug_print;
		bool			is_header_print;
		void			print_debug_info(const char *_format, ...);
		
		bool			is_init;
		bool			is_set_url;
		bool			is_post;
		
		CURL 			*curl_handle;
		CURLcode 		curl_ret_code;
		string 			read_buffer;
		string			url;
		string			data;
		
		struct			curl_slist *headers;
		
		static size_t 		write_callback(void *_contents, size_t _size, size_t _nmemb, void *_userp);
		
	public  :
		CURL_Handler(bool _is_debug_print = false);
		~CURL_Handler(void);
		
		void 			set_debug_print(void);
		void 			set_header_print(void);
		
		bool			init(void);
		void			clear(void);
		
		void			set_header(string _header);
		void			set_header_content(string _content, string _info);
		void			set_post(string _data);
		void			set_url(string _url);
		void			set_server_info(string _target_url);

		
		int			request(void);
		string			response(void);
};

 
#endif

 

2. 소스코드 : src/api_curl.cpp

#include "api_curl.h"

CURL_Handler::CURL_Handler(bool _is_debug_print) {
	this->is_debug_print  = false;
	this->is_header_print = false;

	if( this->is_debug_print ) {
		this->set_debug_print();
	}
	this->print_debug_info("CURL_Handler() create instance\n");


	this->curl_handle = NULL;
	this->clear();
	
	return ;
}

CURL_Handler::~CURL_Handler(void) {
	this->print_debug_info("CURL_Handler() instance destructed\n");
	
	
	if( this->curl_handle != NULL ) { 
		curl_easy_cleanup(this->curl_handle);
		this->curl_handle = NULL;
	}
	
	return ;
}
		
void CURL_Handler::print_debug_info(const char *_format, ...) {
	if( !this->is_debug_print ) return ;
	
	fprintf(stdout, "CURL_Handler::");
	va_list arg;
	va_start(arg, _format);
	vprintf(_format, arg);
	va_end(arg);
	
	return ;
}

void CURL_Handler::set_debug_print(void) {
	this->is_debug_print = true;
	
	this->print_debug_info("set_debug_print() is set on\n");
	
	return ;
}

void CURL_Handler::set_header_print(void) {
	this->is_header_print = true;
	
	this->print_debug_info("set_header_print() is set on\n");
	
	return ;
}

size_t CURL_Handler::write_callback(void *_contents, size_t _size, size_t _nmemb, void *_userp) {
	((string *)_userp)->append((char *)_contents, _size * _nmemb);
	
	return _size * _nmemb;
}

bool CURL_Handler::init(void) {
	if( (this->curl_handle = curl_easy_init()) > 0 ) {
		this->print_debug_info("init() curl_easy_init() success\n");
		this->is_init = true;
		
	} else {
		this->print_debug_info("init() curl_easy_init() failed\n");
		this->is_init = false;
	}
	
	curl_easy_setopt(this->curl_handle, CURLOPT_WRITEFUNCTION, 	this->write_callback);
	curl_easy_setopt(this->curl_handle, CURLOPT_WRITEDATA, 		&this->read_buffer);
	curl_easy_setopt(this->curl_handle, CURLOPT_HTTPHEADER,		this->headers);
	
	if( (this->is_debug_print && this->is_header_print ) ) {  
		curl_easy_setopt(this->curl_handle, CURLOPT_VERBOSE, 	true);
	}
	return this->is_init;
}

void CURL_Handler::clear(void) {
	this->headers		= NULL;

	this->read_buffer	= "";
	this->url		= "";
	this->data		= "";
	
	this->is_init		= false;
	this->is_set_url	= false;
	this->is_post		= false;
	
	if( this->curl_handle != NULL ) { 
		curl_easy_cleanup(this->curl_handle);
		this->curl_handle = NULL;
	}
	
	this->headers = curl_slist_append(this->headers, "Content-Type: application/json");
	
	this->print_debug_info("clear() clear handler\n");
	
	return ;
}

void CURL_Handler::set_header(string _header) {
	if( !this->is_init ) {
		this->print_debug_info("set_header() init not ready\n");
		return ;
	}
	
	this->headers = curl_slist_append(this->headers, _header.c_str());
	this->print_debug_info("set_header() set [%s]\n", _header.c_str());
	
	return ;
}

void CURL_Handler::set_url(string _url) {
	if( !this->is_init ) {
		this->print_debug_info("set_url() init not ready\n");
		return ;
	}
	
	this->print_debug_info("set_url() set [%s]\n", _url.c_str());
	this->is_set_url = true;
	this->url = _url;
	
	return ;
}

void CURL_Handler::set_post(string _data) {
	if( !this->is_init ) {
		this->print_debug_info("set_post() init not ready\n");
		return ;
	}
	
	this->print_debug_info("set_post() set [%s]\n", _data.c_str());
	this->is_post = true;
	this->data = _data;
	
    return ;
}

int	CURL_Handler::request(void) {
	if( !this->is_init ) {
		this->print_debug_info("request() init not ready\n");
		return -1;
	}
	
	if( !this->is_set_url ) {
		this->print_debug_info("request() set not url\n");
		return -1;
	}
	
	this->print_debug_info("request() request [%s] %s\n", 
				this->is_post ? "POST" : "GET", this->url.c_str());
	
	if( this->is_post ) {
		curl_easy_setopt(this->curl_handle, CURLOPT_POSTFIELDS,		this->data.c_str());
		curl_easy_setopt(this->curl_handle, CURLOPT_POSTFIELDSIZE,	this->data.length());
	}
	curl_easy_setopt(this->curl_handle, CURLOPT_URL, this->url.c_str());
	
	this->read_buffer   = "";
	this->curl_ret_code = curl_easy_perform(this->curl_handle);
	
	if( this->curl_ret_code != CURLE_OK ) {
		this->read_buffer = string(curl_easy_strerror(this->curl_ret_code));
	}
	
	return (int)this->curl_ret_code;
}

string CURL_Handler::response(void) {
	
	return this->read_buffer;
}

void CURL_Handler::set_header_content(string _content, string _info) {
	string content = _content;
	content.append(": ");
	content.append(_info);
	
	this->set_header(content);
	
	return ;
}

void CURL_Handler::set_server_info(string _target_url) {
	this->set_url(_target_url);
	
	return ;
}

 

3. 소스코드 : sample.cpp

sample.cpp 에서 위 api_curl library 를 간단하게 사용하는 예제를 보여준다.

set_server_info() 메서드에 curl 을 전송할 대상을 적는다. 

여기선 공개된 Rest API reply server 를 사용하였다.

#include <stdio.h>

#include "api_curl.h"

int main(int _argc, char *_argv[]) {
    CURL_Handler	curl_handle;
    
    curl_handle.set_debug_print();
    curl_handle.init();
		
    curl_handle.set_header_content("Content-Type", 	"application/json");
    
    // POST 사용 시 string data를 인자로 사용
    // curl_handle.set_post(str_curl_data);

    curl_handle.set_server_info("https://httpbin.org/get");
    curl_handle.request();
    
    string response = curl_handle.response();
    
    printf("response : [%s]\n", response.c_str());
    
    curl_handle.clear();

    return 0;
}

 

4. 컴파일 및 실행 결과

# api_curl 라이브러리 생성
muabow@muabow:~/dev/cpp_file/api_curl$ make clean ; make
rm -Rf  ./src/api_curl.o libapi_curl.so
rm -Rf
g++  -fPIC -I./include -lcurl -c src/api_curl.cpp -o src/api_curl.o

# Create library
g++ -shared -o libapi_curl.so  ./src/api_curl.o
muabow@muabow:~/dev/cpp_file/api_curl$

# 샘플 컴파일
muabow@muabow:~/dev/cpp_file/api_curl$ g++ -o sample sample.cpp -I./include -L. -lapi_curl -lcurl -std=c++11

# LD_LIBRARY_PATH 추가
muabow@muabow:~/dev/cpp_file/api_curl$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)

# 샘플 파일 실행
muabow@muabow:~/dev/cpp_file/api_curl$ ./sample
CURL_Handler::set_debug_print() is set on
CURL_Handler::init() curl_easy_init() success
CURL_Handler::set_header() set [Content-Type: application/json]
CURL_Handler::set_url() set [https://httpbin.org/get]
CURL_Handler::request() request [GET] https://httpbin.org/get
response : [{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-61e02c1a-3695de6450096c363303f52c"
  },
  "origin": "1.239.233.108",
  "url": "https://httpbin.org/get"
}
]
CURL_Handler::clear() clear handler
CURL_Handler::CURL_Handler() instance destructed
muabow@muabow:~/dev/cpp_file/api_curl$

응답이 바르게 온 것을 확인할 수 있다.

 

혹시 라이브러리 빌드 및 컴파일 시 curl library 를 찾을 수 없다고 에러가 나면 아래처럼 libcurl 을 설치하자.

sudo apt-get install libcurl4-openssl-dev

많은 도움이 되길 바란다.

 

끝.

 

 

 

C++ curl handler class 예제, C언어 curl 구현

댓글