1. POCO 라이브러리를 설치합니다.
https://pocoproject.org/download.html
POCO C++ Libraries - Simplify C++ Development
The POCO C++ Libraries are powerful cross-platform and open source C++ class libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT and embedded systems.
pocoproject.org
2. vcpkg를 이용하여 쉽게 설치할 수 있습니다.
- vcpkg를 설치합니다.
- vcpkg search poco를 실행한다.
- vcpkg install poco[core,json,net]:x64-windows으로 필요한 라이브러리를 설치한다.
- vcpkg install mariadb-connector-cpp:x64-windows로 mariaDB C++ Connector를
설치한다.(SQL Server로 mariaDB Server를 사용합니다)
3. Database.h 파일을 추가합니다.
#pragma once
#include <mariadb/conncpp.hpp>
#include <memory>
class Database
{
public:
static std::unique_ptr<sql::Connection> GetConnection();
private:
static constexpr const char* URL = "jdbc:mariadb://127.0.0.1:3306/database1";
static constexpr const char* USER = "user1";
static constexpr const char* PASSWORD = "password1";
};
4. Database.cpp 파일을 추가합니다.
#include "Database.h"
#include <iostream>
#include <cstdlib>
std::unique_ptr<sql::Connection>
Database::GetConnection()
{
sql::SQLString url(URL);
sql::Properties properties(
{
{"user", USER},
{"password", PASSWORD},
});
_putenv_s("MARIADB_TLS_DISABLE_PEER_VERIFICATION", "1");
sql::Driver* driver = sql::mariadb::get_driver_instance();
std::unique_ptr<sql::Connection> conn;
try {
conn.reset(driver->connect(url, properties));
}
catch (sql::SQLException& e)
{
std::cerr << "Connection error: " << e.what() << std::endl;
return nullptr;
}
return conn;
}
5. MemberHandler.h 파일을 추가합니다.
#pragma once
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
class MemberHandler : public Poco::Net::HTTPRequestHandler
{
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;
};
6. MemberHandler.cpp 파일을 추가합니다.
#include "MemberHandler.h"
#include "Database.h"
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Array.h>
#include <Poco/JSON/Stringifier.h>
#include <Poco/Dynamic/Var.h>
#include <Poco/JSON/Parser.h>
//#include <mysql/jdbc.h>
#include <mariadb/conncpp.hpp>
#include <sstream>
using namespace Poco::JSON;
using namespace Poco::Net;
void MemberHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
if (request.getMethod() == "GET")
{
std::cout << "GET request received" << std::endl;
std::string uri = request.getURI();
if (uri == "/")
{
Poco::JSON::Object result;
result.set("success", false);
result.set("message", "POCO REST Server Running");
std::stringstream ss;
result.stringify(ss);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << ss.str();
}
else if (uri == "/members")
{
auto conn = Database::GetConnection();
std::unique_ptr<sql::PreparedStatement> pstmt{ conn->prepareStatement("SELECT id, name, image_id FROM member") };
std::unique_ptr<sql::ResultSet> rs{ pstmt->executeQuery() };
Array arr;
while (rs->next())
{
Object::Ptr obj = new Object;
auto setStringOrNull = [&](const std::string& key)
{
auto value = rs->getString(key);
if (rs->wasNull())
obj->set(key, Poco::Dynamic::Var());
else
obj->set(key, std::string(value.c_str()));
};
obj->set("id", rs->getInt("id"));
setStringOrNull("name");
obj->set("image_id", rs->getInt("image_id"));
arr.add(obj);
}
response.setContentType("application/json");
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
arr.stringify(response.send());
}
}
if (request.getMethod() == "POST")
{
std::cout << "POST request received" << std::endl;
std::string uri = request.getURI();
if (uri == "/members")
{
std::istream& in = request.stream();
std::string body(std::istreambuf_iterator<char>(in), {});
Parser parser;
Poco::Dynamic::Var result = parser.parse(body);
Object::Ptr j = result.extract<Object::Ptr>();
auto conn = Database::GetConnection();
auto pstmt =
conn->prepareStatement(
"INSERT INTO member (name, image_id) VALUES (?, ?)");
pstmt->setString(1, j->getValue<std::string>("name"));
pstmt->setInt(2, j->getValue<int>("image_id"));
pstmt->executeUpdate();
Object obj;
obj.set("success", true);
obj.set("message", "member created");
response.setStatus(Poco::Net::HTTPResponse::HTTP_CREATED);
response.setContentType("application/json");
std::stringstream ss;
obj.stringify(ss);
response.send() << ss.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
if (request.getMethod() == "PUT")
{
std::cout << "PUT request received" << std::endl;
std::string uri = request.getURI();
std::vector<std::string> parts;
std::stringstream ss(uri);
std::string part;
while (std::getline(ss, part, '/'))
{
if (!part.empty())
{
parts.push_back(part);
}
}
if (parts.size() == 2 && parts[0] == "members")
{
int id = std::stoi(parts[1]);
std::istream& in = request.stream();
std::string body(std::istreambuf_iterator<char>(in), {});
Poco::JSON::Parser parser;
auto parsed = parser.parse(body);
auto obj = parsed.extract<Poco::JSON::Object::Ptr>();
std::string name = obj->getValue<std::string>("name");
int image_id = obj->getValue<int>("image_id");
auto conn = Database::GetConnection();
auto pstmt = conn->prepareStatement("UPDATE member SET name=?, image_id=? WHERE id=?");
pstmt->setString(1, name);
pstmt->setInt(2, image_id);
pstmt->setInt(3, id);
pstmt->executeUpdate();
Poco::JSON::Object result;
result.set("success", true);
result.set("message", "member updated");
result.set("id", id);
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
response.setContentType("application/json");
std::stringstream out;
result.stringify(out);
response.send() << out.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
if (request.getMethod() == "DELETE")
{
std::cout << "DELETE request received" << std::endl;
std::string uri = request.getURI();
std::vector<std::string> parts;
std::stringstream ss(uri);
std::string part;
while (std::getline(ss, part, '/'))
{
if (!part.empty())
{
parts.push_back(part);
}
}
if (parts.size() == 2 && parts[0] == "members")
{
int id = std::stoi(parts[1]);
auto conn = Database::GetConnection();
auto pstmt = conn->prepareStatement("DELETE FROM member WHERE id=?");
pstmt->setInt(1, id);
pstmt->executeUpdate();
Poco::JSON::Object result;
result.set("success", true);
result.set("message", "member deleted");
std::stringstream out;
result.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
response.setContentType("application/json");
response.send() << out.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
}
7. ImageHandler.h 파일을 추가합니다.
#pragma once
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
class ImageHandler : public Poco::Net::HTTPRequestHandler
{
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;
};
8. ImageHandler.cpp 파일을 추가합니다.
#include "ImageHandler.h"
#include "Database.h"
#include "Poco/FileStream.h"
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Array.h>
#include <Poco/JSON/Stringifier.h>
#include <Poco/Dynamic/Var.h>
#include <Poco/JSON/Parser.h>
using namespace Poco::JSON;
using namespace Poco::Net;
void ImageHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
response.setContentType("application/json");
auto conn = Database::GetConnection();
if (request.getMethod() == "GET")
{
std::cout << "GET request received" << std::endl;
std::string uri = request.getURI();
std::vector<std::string> parts;
std::stringstream ss(uri);
std::string part;
while (std::getline(ss, part, '/'))
{
if (!part.empty())
{
parts.push_back(part);
}
}
if (parts.size() == 0)
{
Poco::JSON::Object result;
result.set("success", false);
result.set("message", "POCO REST Server Running");
std::stringstream ss;
result.stringify(ss);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << ss.str();
}
else if (parts.size() == 1 && parts[0] == "images")
{
std::unique_ptr<sql::PreparedStatement> pstmt{ conn->prepareStatement("SELECT id, file FROM image") };
std::unique_ptr<sql::ResultSet> rs{ pstmt->executeQuery() };
Array arr;
while (rs->next())
{
Object::Ptr obj = new Object;
auto setStringOrNull = [&](const std::string& key)
{
auto value = rs->getString(key);
if (rs->wasNull())
obj->set(key, Poco::Dynamic::Var());
else
obj->set(key, std::string(value.c_str()));
};
obj->set("id", rs->getInt("id"));
setStringOrNull("file");
arr.add(obj);
}
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
arr.stringify(response.send());
}
else if (parts.size() == 2 && parts[0] == "images")
{
int id = std::stoi(parts[1]);
std::string filename;
auto pstmt = std::unique_ptr<sql::PreparedStatement>{ conn->prepareStatement("SELECT file FROM image WHERE id=?") };
pstmt->setInt(1, id);
auto res = std::unique_ptr<sql::ResultSet>{ pstmt->executeQuery() };
if (res->next())
{
filename = res->getString("file");
}
response.setContentType("image/jpg");
Poco::FileInputStream fis(filename, std::ios::binary);
std::ostream& out = response.send();
char buffer[4096];
while (fis.good())
{
fis.read(buffer, sizeof(buffer));
std::streamsize n = fis.gcount();
if (n > 0)
out.write(buffer, n);
}
}
}
if (request.getMethod() == "POST")
{
std::cout << "POST request received" << std::endl;
std::string uri = request.getURI();
if (uri == "/images")
{
std::istream& in = request.stream();
std::string body(std::istreambuf_iterator<char>(in), {});
Parser parser;
Poco::Dynamic::Var result = parser.parse(body);
Object::Ptr j = result.extract<Object::Ptr>();
auto conn = Database::GetConnection();
auto pstmt =
conn->prepareStatement(
"INSERT INTO member (file VALUES (?)");
pstmt->setString(1, j->getValue<std::string>("file"));
pstmt->executeUpdate();
Object obj;
obj.set("success", true);
obj.set("message", "image created");
response.setStatus(Poco::Net::HTTPResponse::HTTP_CREATED);
response.setContentType("application/json");
std::stringstream ss;
obj.stringify(ss);
response.send() << ss.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
if (request.getMethod() == "PUT")
{
std::cout << "PUT request received" << std::endl;
std::string uri = request.getURI();
std::vector<std::string> parts;
std::stringstream ss(uri);
std::string part;
while (std::getline(ss, part, '/'))
{
if (!part.empty())
{
parts.push_back(part);
}
}
if (parts.size() == 2 && parts[0] == "images")
{
int id = std::stoi(parts[1]);
std::istream& in = request.stream();
std::string body(std::istreambuf_iterator<char>(in), {});
Poco::JSON::Parser parser;
auto parsed = parser.parse(body);
auto obj = parsed.extract<Poco::JSON::Object::Ptr>();
std::string file = obj->getValue<std::string>("file");
auto conn = Database::GetConnection();
auto pstmt = conn->prepareStatement("UPDATE image SET file=? WHERE id=?");
pstmt->setString(1, file);
pstmt->setInt(3, id);
pstmt->executeUpdate();
Poco::JSON::Object result;
result.set("success", true);
result.set("message", "image updated");
result.set("id", id);
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
response.setContentType("application/json");
std::stringstream out;
result.stringify(out);
response.send() << out.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
if (request.getMethod() == "DELETE")
{
std::cout << "DELETE request received" << std::endl;
std::string uri = request.getURI();
std::vector<std::string> parts;
std::stringstream ss(uri);
std::string part;
while (std::getline(ss, part, '/'))
{
if (!part.empty())
{
parts.push_back(part);
}
}
if (parts.size() == 2 && parts[0] == "images")
{
int id = std::stoi(parts[1]);
auto conn = Database::GetConnection();
auto pstmt = conn->prepareStatement("DELETE FROM image WHERE id=?");
pstmt->setInt(1, id);
pstmt->executeUpdate();
Poco::JSON::Object result;
result.set("success", true);
result.set("message", "image deleted");
std::stringstream out;
result.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
response.setContentType("application/json");
response.send() << out.str();
}
else
{
Poco::JSON::Object error;
error.set("success", false);
error.set("message", "invalid uri");
std::stringstream out;
error.stringify(out);
response.setStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
response.setContentType("application/json");
response.send() << out.str();
}
}
}
9. NullHandler.h 파일을 추가합니다.
#pragma once
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
class NullHandler : public Poco::Net::HTTPRequestHandler
{
public:
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override;
};
10. NullHandler.cpp 파일을 추가합니다.
#include "NullHandler.h"
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Stringifier.h>
void NullHandler::handleRequest(
Poco::Net::HTTPServerRequest& request,
Poco::Net::HTTPServerResponse& response
)
{
Poco::JSON::Object json;
json.set("success", false);
json.set("error", "Invalid API endpoint");
json.set("uri", request.getURI());
response.setStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
response.setContentType("application/json");
std::ostream& os = response.send();
json.stringify(os);
}
11. Factory.h 파일을 추가합니다.
#pragma once
#include <memory>
#include "MemberHandler.h"
#include "ImageHandler.h"
#include "NullHandler.h"
#include <Poco/Net/HTTPRequestHandlerFactory.h>
class Factory : public Poco::Net::HTTPRequestHandlerFactory
{
public:
Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override
{
constexpr auto MEMBERS = "/members/";
constexpr auto IMAGES = "/image/";
std::string uri = request.getURI();
if (uri == "/members" || uri.starts_with(MEMBERS))
return new MemberHandler();
if (uri == "/images" || uri.starts_with(IMAGES))
return new ImageHandler();
return new NullHandler();
}
};
12. main.cpp파일을 추가합니다.
#include "MemberHandler.h"
#include "ImageHandler.h"
#include "Factory.h"
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/ServerSocket.h>
#include <iostream>
using namespace Poco::Net;
int main()
{
ServerSocket socket(8080);
HTTPServer server(new Factory(), socket, new HTTPServerParams);
server.start();
std::cout << "REST Server Start : 8080\n";
getchar();
server.stop();
return 0;
}
13. 프로젝트를 실행합니다.
* 참고
- C++ : Poco라이브러리로 REST API 서버 만들기(1)
C++ : Poco라이브러리로 REST API 서버 만들기(1)
1. POCO 라이브러리를 설치합니다.https://pocoproject.org/download.html POCO C++ Libraries - Simplify C++ DevelopmentThe POCO C++ Libraries are powerful cross-platform and open source C++ class libraries for building network- and internet-based ap
taekho.tistory.com
- C++ : Poco라이브러리로 REST API 서버 만들기(3)
'C_C++' 카테고리의 다른 글
| C++ : Poco라이브러리로 REST API 서버 만들기(3) (0) | 2026.06.01 |
|---|---|
| C++ : Poco라이브러리로 REST API 서버 만들기(1) (0) | 2026.06.01 |
| C++ : 배열eotls modern C++ std::vector 사용하기 (0) | 2026.05.23 |
| C++ : matiaDB ODBC 설치하기 (0) | 2026.05.08 |
| C++ : Visual Studio에서 Static Library 제작 및 사용하기 (0) | 2026.05.02 |