C++ REST SDK를 이용한 HTTP Request

Brie·2023년 11월 6일
0

C++

목록 보기
5/9

개요

해당 문서에서는 C++에서 cpprestsdk를 통해 REST API Server에게 HTTP Request를 보내고 응답을 받는 방법에 대해 설명한다.

cpprestsdk

Microsoft에서 만든 클라이언트, 서버용 C++ HTTP 통신 모듈이며, JSON URI, 비동기 통신, 웹소켓, oAuth 등을 지원한다.

cpprestsdk에서 제공하고 있는 Namespaces, classes, files 등에 대한 정보는 해당 문서에서 확인할 수 있다.

환경 설정

개발 환경은 다음과 같은 운영체제와 IDE를 사용하였다.

  • OS: Windows 11 Home 22H2
  • IDE: Visual Studio 2022

패키지 관리(vcpkg, NuGet)

cpprestsdk를 설치하는 데에는 대표적으로 두 가지 방법이 있는데, 첫 번째는 vcpkg를 통해 패키지를 설치하는 것이고 두 번째는 Visual Studio의 NuGet 패키지 관리를 통해 설치하는 방법이다.

설치 방법

  • vcpkg를 사용하는 경우, 다음과 같이 command line를 통해 cpprestsdk를 설치하고 관리한다. 이는 빌드 및 의존성 관리를 쉽게 할 수 있는 방법이지만 프로젝트 설정에 대한 몇 가지 추가 단계가 필요하다.
D:\vcpkg>vcpkg search cpprestsdk
bitserializer[cpprestjson-archive]        Module for support JSON (implementation based on the CppRestSDK library)
cpprestsdk               2.10.18#4        C++11 JSON, REST, and OAuth library

D:\vcpkg>vcpkg install cpprestsdk cpprestsdk:x64-windows
Computing installation plan...

... 생략 ...

-- Installing: D:/vcpkg/packages/cpprestsdk_x64-windows/share/cpprestsdk/copyright
-- Performing post-build validation
Stored binaries in 1 destinations in 924 ms.
Elapsed time to handle cpprestsdk:x64-windows: 1.4 min
Total install time: 2.6 min
cpprestsdk provides CMake targets:

  # this is heuristically generated, and may not be correct
  find_package(cpprestsdk CONFIG REQUIRED)
  target_link_libraries(main PRIVATE cpprestsdk::cpprest cpprestsdk::cpprestsdk_zlib_internal cpprestsdk::cpprestsdk_brotli_internal)
  • Visual Studio의 NuGet 패키지 관리를 사용하면 Visual Studio 내에서 패키지를 검색하고 설치할 수 있으며 프로젝트 설정이 자동으로 처리된다.

    1. 프로젝트 생성 후 솔루션 탐색기->프로젝트 우클릭 ->NuGet 패키지 관리 클릭

    2. CPPREST 검색 후 패키지 설치

    3. 설치 완료 시 다음과 같이 솔루션 폴더 내부의 패키지 폴더에서 cpprestsdk가 설치된 것을 확인할 수 있다.

의존성 관리

  • vcpkg를 사용하면 의존성 패키지의 버전 관리 및 업데이트가 비교적 수동적이며 패키지 간의 충돌을 피하기 위해 몇 가지 설정이 필요할 수 있다.
  • NuGet을 사용하면 의존성 패키지의 버전 관리가 쉽고, 필요한 경우 자동으로 업데이트할 수 있다.

통합

  • Visual Studio의 NuGet 패키지 관리는 Visual Studio 환경 내에서 통합되므로 프로젝트 설정과 관련하여 편리하다. 그러나 다른 개발 환경에서는 추가 구성이 필요할 수 있다.
  • vcpkg를 사용하는 경우, 여러 개발 환경에서 동일한 방식으로 패키지를 관리할 수 있으므로 이식성이 높다.

httpRequest.cpp

코드를 작성하기 위해 Visual Studio에서 httpRequest.cpp라는 소스 파일을 생성하였다.

#include <iostream>
#include <cpprest/http_client.h>

// #pragma comment(lib,"cpprest141_2_10.libs")

using namespace std; // 표준 라이브러리 사용
using namespace web;
using namespace web::http;
using namespace web::http::client;

HTTP Request를 보내기 위한 기능을 제공하는 cpprest의 헤더 파일을 include하고 namespace를 설정한다.

vcpkg를 통해 라이브러리를 Visual Studio와 통합(vcpkg integrate install)한 경우, 링커 연결을 하지 않아도 헤더 파일을 include하여 사용할 수 있다.

라이브러리 링크와 관련해서는 해당 문서를 참조한다.

void HttpRequest() {
  // HTTP 클라이언트를 초기화하고 요청을 보낼 URL을 지정
  // 여기서는 테스트용 웹사이트인 httpbin.org를 URL로 설정
  http_client client(U("http://httpbin.org/get"));

  // HTTP Request를 생성하고 method는 GET으로 설정
  http_request req(methods::GET);
}

Request를 보내기 위한 HttpRequest() 함수를 생성하고, 대상과 http 연결을 맺기 위한 http_client 클래스와 HTTP GET 요청을 보내기 위한 http_request 클래스를 선언하였다.

	// sync request (동기 방식)
	http_response resp = client.request(req).get();
	wcout << resp.status_code() << " : sync request" << endl; // status_code 출력
	wcout << U("content-type : ") << resp.headers().content_type() << endl; // content-type 출력
	
	wcout << resp.extract_json(true).get() << endl; // 응답에 대해 json으로 추출된 값을 출력
	
	wcout << ("----------------") << endl;

client를 대상으로 get request를 보내, 응답에 대해 http_response 클래스로 받는다.

‘get()’ 함수는 HTTP 요청을 동기적으로 보내고 해당 요청에 대한 응답을 기다리는 메서드이다. 이 함수는 HTTP 요청을 보내고, 응답을 받을 때까지 현재 스레드를 차단(block)시킨다. 즉, get() 함수가 완료될 때까지 다음 코드 라인으로 진행하지 않는 동기 방식이다.

(비동기 방식은 코드 작성은 하였으나 테스트 과정에서 문제가 발생하여 차후 업로드하겠습니다.)

Full Code

#include <iostream>
#include <cpprest/http_client.h>

// #pragma comment(lib,"cpprest141_2_10.libs")

using namespace std; // 표준 라이브러리 사용
using namespace web;
using namespace web::http;
using namespace web::http::client;

void HttpRequest() {
    // HTTP 클라이언트를 초기화하고 요청을 보낼 URL을 지정
    // 여기서는 테스트용 웹사이트인 httpbin.org를 URL로 설정
    http_client client(U("http://httpbin.org/get"));

    // HTTP Request를 생성하고 method는 GET으로 설정
    http_request req(methods::GET);

    // sync request (동기 방식)
    http_response resp = client.request(req).get();
    wcout << resp.status_code() << " : sync request" << endl;
    wcout << U("content-type : ") << resp.headers().content_type() << endl;

    wcout << resp.extract_json(true).get() << endl;

    wcout << ("----------------") << endl;

    // async request (비동기 방식)
    client.request(req).then([=](http_response resp) {
        wcout << resp.status_code() << " : async request" << endl;
        wcout << U("content-type : ") << resp.headers().content_type() << endl;

        resp.extract_json(true).then([](json::value v) {
            wcout << v << endl;
            }).wait();

        }).wait();
}

int main()
{
    // wcout.imbue(locale("kor"));  // 한국어 출력 안될 경우 locale 설정
    HttpRequest();

    return 0;
}

0개의 댓글