á€áá±á¬ááºážáá«ážááœáẠdocker/docker-compose ááŸáá·áº conan áááºáá±á·áá»áºáááºáá±áá»á¬ááᯠá¡áá¯á¶ážááŒá¯á C++ ááœáẠREST API áááºáá±á¬ááºááŸá¯ááá¯áá±ážáá¬ážáááºá¡ááœáẠáá¯á¶á á¶áááááºáá áºáᯠ(cookiecutter) ááᯠáááºáá®ážáá¯á¶á¡ááŒá±á¬ááºáž ááŒá±á¬ááŒáá«áááºá
áá±á¬ááºáá
áºááŒááẠáááºáá¬ááœááºááœáẠáá»áœááºá¯ááºááẠáá±á¬ááºáá¶áá±á¬á·ááºáá²áá±ážáá¬ážáá°á¡ááŒá
Ạáá«áááºáá²á·áá¬ááœáẠáá±á¬ááºááẠááá¯ááºáááá¯áá¬ážáá
áºááᯠáá±ážááẠáá¬ááá¯á¡áá¯á¶ážááŒá¯ááááºáááºážá á¡áá¯áá áá±ážáá¬ážááá»áŸá áá«áá²á· áá«á·áá¬áá¬áá±ážáá¬ážáá¬
ááá¯á·ááŒá±á¬áá·áºá áá»áœááºá¯ááºááá¯á·ááẠhigh-load service ááá¯áá±ážáá¬ážáááºáá¬áááºááŸáá·áºáááºááá¯ááºáá²á·ááááºá áááºážáá¡ááááá¬áááºááŸá¬áááºážááá¯á·áá¬ááá·áºáá±áá¬ááá¯ááŒáá¯áááºáá¯ááºáá±á¬ááºááŒá®ážáá±áá¬áá±á·á áºááá¯á·áá±ážáááºááŒá áºáááºá áá±á¬ááºááẠáá±ážááááºááŒááºááŒá®ážáá±á¬áẠáá°áááºáá»ááºážáá áºáá±á¬ááºá C++ developer áá áºáá±á¬ááºá¡áá±áá²á· á¡á¬ážáá¬áá»ááºááœá±ááᯠá¡áá¯á¶ážááŒá¯ááŒá®áž áá®áááºáá±á¬ááºááŸá¯ááá¯áá±ážááá¯á· á¡ááŒá¶ááŒá¯áá²á·áá«áááºá áááºážááᯠá á±á¬áááááºáááŒááºážááŸá¬ áááºážááẠááá¯ááá¯ááŒááºáááºá ááá¯ááá¯á¡áá»áá¯ážááŒá áºááœááºážá á±áááºááŒá áºáᬠáá±áá¯áá»á¡á¬ážááŒáá·áº áá»á°áá®áá°ááŒá®ážáá»á¬ážááẠá¡ááœá²á·áá¡áááºážá¡ááŒá áºáá»á¬ážááᯠá á®áá¶ááá·áºááœá²áááºážááᯠáá»áœááºá¯ááºááá¯á·áááá¬ážáá¯á¶ááŸáá·áºáááºáááºá áááºážááŒá±á¬ááºáááºážáá¬ááŒá áºáá«áááºá áá»áœááºá¯ááºááẠC++ ááœáẠááá¯ááá¯á·áá±á¬ á¡áá¬áá»á¬ážááᯠáá áºáá«áá»áŸ ááá¯ááºáá°ážááŒá±á¬ááºážááŸáá·áº áá»ááºááŸááá±á¬ áá¬áá®áá±á«ááºáž 20+ ááᯠááá·áºáá»á±á¬áºáá±á¬ á á¬ááŒáá·áºááá¯ááºáá»á¬ážááᯠááŸá¬ááœá±ááŒááºážá á á¯á ááºážááŒááºážááŸáá·áº áá»áááºáááºááŒááºážá¡ááœáẠááœááºáá°á áœá¬ ááŒáŸá¯ááºááŸá¶ááá¯ááºáááºáᯠááŒá±ááŒá¬ážáá²á·áááºá ááá¯ážááá¯ážááŸááºážááŸááºážááŒá±á¬áááẠáá»áœááºáá±á¬áº ááá·áºááœá¬ážáááºá á¡á²áá«ááᯠáá»áœááºáá±á¬áºááá¯á· áá¯á¶ážááŒááºááŒá®áž Python ááŸá¬ á¡áá¬á¡á¬ážáá¯á¶ážááᯠá¡á±ážá¡á±ážáá±ážáá±áž ááŒá®ážááœá¬ážáá«ááŒá®á
ááá¯á á¡áááºážá¡ááŒáẠáá®ážááá·áºááœá²áá¯ááºáá±áá»áááºá¡ááœááºáž C++ ááœáẠáááºáá±á¬ááºááŸá¯áá»á¬ážááᯠáááºááá¯á·áá±ážááááºááᯠá¡ááŒá±ááŸá¬ááẠáá¯á¶ážááŒááºáá²á·áááºá ááááá¯á¶ážáá¯ááºáááŸá¬á ááá·áºáá±á¬áºáá²á· á
á¬ááŒáá·áºááá¯ááºáá
áºáá¯ááᯠáá¯á¶ážááŒááºáá«á áá»áœááºáá±á¬á·áºáá²á· ááœá±ážáá»ááºááŸá¯ áá»ááœá¬ážáá²á·áááºá
conanfile.txt
[ááá¯á¡ááºáááº]
poco/1.9.3
libpq/11.5
ááá¯ážááŸááºážáá±á¬ command ááŒáá·áº "conan install ." ááá¯á¡ááºáá±á¬á á¬ááŒáá·áºááá¯ááºáá»á¬ážááᯠinstall áá¯ááºáá«á ááá¬áá¡ááá¯ááºáž ááŒá¯ááŒááºááŒá±á¬ááºážáá²áááºáááºáž ááá¯á¡ááºáá«áááºá
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
á¡á²áá®áá±á¬ááºááŸá¬áá±á¬á· PostgreSQL áá²á· á¡áá¯ááºáá¯ááºááá¯á· á á¬ááŒáá·áºááá¯ááºáá áºáá¯ááᯠá áááºááŸá¬ááœá±áá²á·áááºá á¡á²áá«á áá»áœááºáá±á¬áºáá²á· á¡áá¯ááºááœá²áá¯ááºááá²á· á¡ááœá±á·á¡ááŒá¯á¶áááºážáá²á·á¡ááœááºááŒá±á¬áá·áºáá²á á¡á²áá«á áá»áœááºá¯ááºááá¯á·áá²á· Python áááºáá±á¬ááºááŸá¯ááœá±áá²á· á¡ááŒááºá¡ááŸááºá¡áá»áá¯ážááŒá¯áá²á· áá áºáá¯áááºáž ááŒá áºáá«áááºá áá«áááºáá°áá²á·áá¬ááᯠáááºážáááá¬ážá POCO ááœááºááŸááááºá ááá¯á·áá±á¬áº conan ááẠPOCO ááœááºááŸáááŒá±á¬ááºážááŸáá·áº áááºážááᯠáááºááá¯á·áááºáá±á¬ááºááááºááᯠááááá«; repository ááœáẠáá±ááºááá®áá±á¬á·áá±á¬ ááœá²á·á ááºážááŸá¯áá¯á¶á á¶ááá¯ááºáá áºáᯠááŸáááẠ(POCO áááºáá®ážáá°áá»á¬ážáᶠá€á¡ááŸá¬ážá¡ááŒá±á¬ááºáž áá»áœááºá¯ááºáá±ážááŒá®ážááŒá®)á ááá¯ááá¯áááºááŸá¬ áááºááẠá¡ááŒá¬ážá á¬ááŒáá·áºááá¯ááºáá áºáá¯ááᯠááŸá¬ááœá±ááááºáᯠááá¯ááá¯áááºá
ááá¯á·áá±á¬ááºááœáẠáá»áœááºá¯ááºáááœá±ážáá»ááºááŸá¯ááẠáá°ááŒáá¯ááºáááºážáá±á¬ á
á¬ááŒáá·áºááá¯ááºááœáẠáá»ááœá¬ážáááºá
áá±á¬ááºáá
áºááá·áºááŸá¬ áá±á¬ááºážááá¯ááŸá¯áá»á¬ážááᯠáá¯ááºáá±á¬ááºááá¯ááºááá·áº áááºáá±á¬ááºááŸá¯áá¯á¶á
á¶áá
áºáá¯ááᯠáá±ážáááºááŒá
áºáááºá
áá»áœááºá¯ááºááá¯á·ááẠPoco::Util::ServerApplication á០áá»áœááºá¯ááºááá¯á·á TemplateServerApp á¡áááºážááᯠá¡ááœá±ááááºááŒá
áºááŒá®áž áááºááááºážáááºážááᯠá¡á
á¬ážááá¯ážááá«áááºá
TemplateServerApp
#pragma once
#include <string>
#include <vector>
#include <Poco/Util/ServerApplication.h>
class TemplateServerApp : public Poco::Util::ServerApplication
{
protected:
int main(const std::vector<std::string> &);
};
int TemplateServerApp::main(const vector<string> &)
{
HTTPServerParams* pParams = new HTTPServerParams;
pParams->setMaxQueued(100);
pParams->setMaxThreads(16);
HTTPServer s(new TemplateRequestHandlerFactory, ServerSocket(8000), pParams);
s.start();
cerr << "Server started" << endl;
waitForTerminationRequest(); // wait for CTRL-C or kill
cerr << "Shutting down..." << endl;
s.stop();
return Application::EXIT_OK;
}
áááºááááºážáááºážááœáẠáá»áœááºá¯ááºááá¯á·ááẠááá¯á·ááºá á á¬ááœá²á¡áá±á¡ááœááºááŸáá·áº áááºážá á®á¡ááœááºá¡á á¬ážááᯠáááºááŸááºááá«áááºá á¡áá±ážá¡ááŒá®ážáá¯á¶ážááá±á¬á·á áááºáá¬áá²á·áá±á¬ááºážááá¯ááŸá¯ááœá±á¡ááœáẠááá¯ááºááœááºáá°ááᯠáááºááŸááºááá«áááºá áá«ááᯠá ááºáá¯á¶áá áºáᯠáááºáá®ážááŒá®áž áá¯ááºáááºá
TemplateRequestHandlerFactory
class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
{
return new TemplateServerAppHandler;
}
};
áá»áœááºáá±á¬á·áºááá á¹á ááŸá¬á TemplateServerAppHandler ááẠá¡áá»áááºááá¯ááºáž áá°áá®áá±á¬ááá¯ááºááœááºáá°ááᯠáááºáá®ážáá±ážáááºá á€áá±áá¬ááœáẠáá»áœááºá¯ááºááá¯á·á áá¯ááºáááºážááá¯ááºáᬠáá¯áá¹ááááᯠáá¬ážááŸáááá¯ááºáá«áááºá
TemplateServerAppHandler
class TemplateServerAppHandler : public HTTPRequestHandler
{
public:
void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
{
URI uri(req.getURI());
string method = req.getMethod();
cerr << "URI: " << uri.toString() << endl;
cerr << "Method: " << req.getMethod() << endl;
StringTokenizer tokenizer(uri.getPath(), "/", StringTokenizer::TOK_TRIM);
HTMLForm form(req,req.stream());
if(!method.compare("POST"))
{
cerr << "POST" << endl;
}
else if(!method.compare("PUT"))
{
cerr << "PUT" << endl;
}
else if(!method.compare("DELETE"))
{
cerr << "DELETE" << endl;
}
resp.setStatus(HTTPResponse::HTTP_OK);
resp.setContentType("application/json");
ostream& out = resp.send();
out << "{"hello":"heh"}" << endl;
out.flush();
}
};
PostgreSQL ááŸáá·áºá¡áá¯ááºáá¯ááºááẠá¡áááºážáá¯á¶á á¶ááá¯áááºáž áááºáá®ážáá²á·áááºá ááá¬ážáá áºáá¯áááºáá®ážááŒááºážáá²á·ááá¯á·áá±á¬ááá¯ážááŸááºážáá±á¬ SQL ááá¯áá¯ááºáá±á¬ááºáááºáááºážáááºážáá áºáá¯ááŸááááºá ExecuteSQL(). ááá¯ááá¯ááŸá¯ááºááœá±ážáá±á¬áá±ážááŒááºážááŸá¯áá»á¬áž ááá¯á·ááá¯áẠáá±áá¬ááŒááºáááºááá°áááºá¡ááœááºá áááºááẠáá áºááá·áºáá¶áá»áááºáááºááŸá¯ááᯠááá°ááááºááŒá áºáááºá GetConnection() ááŸáá·áº libpg API ááá¯áá¯á¶ážáá«á (ááŒá áºáá±á¬ááºážááŒá áºááá¯áẠáá®áááá¬ážááŸá¯ááᯠáá±á¬ááºá០ááŒááºáá±ážáá«á·áááº)á
áá±áá¬áá±á·á
#pragma once
#include <memory>
#include <mutex>
#include <libpq-fe.h>
class Database
{
public:
Database();
std::shared_ptr<PGconn> GetConnection() const;
bool ExecuteSQL(const std::string& sql);
private:
void establish_connection();
void LoadEnvVariables();
std::string m_dbhost;
int m_dbport;
std::string m_dbname;
std::string m_dbuser;
std::string m_dbpass;
std::shared_ptr<PGconn> m_connection;
};
áá±áá¬áá±á·á áºááá¯á· áá»áááºáááºááŒááºážá¡ááœáẠááá·áºáááºáá±á¬ááºá¡á¬ážáá¯á¶ážááᯠáááºáááºážáá»ááºá០áá°áá±á¬ááºááœá¬ážáá±á¬ááŒá±á¬áá·áº .env ááá¯ááºááᯠáááºáá®ážááŒá®áž ááŒááºáááºáááºááŸááºááẠááá¯á¡ááºáá«áááºá
.env
DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432
áá¯ááºááœá±á¡á¬ážáá¯á¶ážááᯠááŒáá·áºááá¯ááºáá«áááºá
ááá¯ááœáẠdockerfile ááŸáá·áº docker-compose.yml ááá¯áá±ážáá¬ážááŒááºážááá±á¬ááºáá¯á¶ážá¡ááá·áºáá±á¬ááºáá¬áááºá ááá¯ážááá¯ážáá¬ážáá¬ážááŒá±á¬ááá»áŸáẠá€á¡áá¬ááẠá¡áá»áááºá¡áá»á¬ážá á¯áá°áá²á·ááááºá áá»áœááºá¯ááºááẠáá°ááá¯ážáá áºáŠážááŒá áºáá±á¬ááŒá±á¬áá·áºáá¬ááá á á¬ááŒáá·áºááá¯ááºáá»á¬ážááᯠá¡áá»áááºááá¯ááºážááŒááºáááºáááºáá±á¬ááºááẠááá¯á¡ááºáá±á¬ááŒá±á¬áá·áºá ááá¯áááºááá»áá¯á·ááœááºážáá»ááºáá»á¬ážááŒá±á¬áá·áºááŒá áºáááºá á¥ááá¬á¡á¬ážááŒáá·áºá conan ááᯠáá±á«ááºážáá¯ááºáá¯ááºáááºá ááá·áºááœááºážáááºááŸáá·áº ááá¯á¡ááºáá±á¬ ááŸá®ááá¯ááŸá¯áá»á¬ážááᯠáááºáá±á¬ááºáááºá¡ááœáẠ"conan install" ááᯠáá±á«ááºážáá¯ááºáá¯ááºááẠáááºážááẠááá¯á¶áá±á¬ááºáá«á ááá¯á·ááá¯ááºáá«á -s compiler.libcxx=libstdc++11 áá±á¬ááºááᯠáá»á±á¬áºááœá¬ážáááºááá¯á¡ááºáá«áááºá ááá·áºáá»áŸá±á¬ááºááœáŸá¬ááᯠáá»áááºáááºááá·áºá¡ááá·áºááœáẠá¡ááŸá¬ážá¡ááœááºážáá»á¬ážá áœá¬ááᯠáááºáááá¯ááºááŒá±ááŸááááºá áá®á¡ááŸá¬ážááᯠáá¬áá®á¡áá±á¬áºááŒá¬á¡á±á¬áẠááááºáááá±áá²á·ááŒá®áž áá®áá±á¬ááºážáá«ážá áááŒá¬ážáá°ááœá±ááᯠáá®ááŒá¿áá¬ááᯠá¡áá»áááºááá¯á¡ááœááºáž ááŒá±ááŸááºážááá¯ááºáááá·áºáááºááá¯á· áá»áŸá±á¬áºááá·áºáá«áááºá
ááá¯á·áá±á¬ááºá docker-compose.yml ááá¯áá±ážááŒá®ážáá±á¬ááºá áá»áœááºá¯ááºááá°áááºáá»ááºážáá¡ááŒá¶áá±ážáá»ááºá¡áá áá»áœááºá¯ááºááẠáá¶á·ááá¯ážáá°áá®ááŸá¯á¡á¬áž áááºáá±á¬ááºážááá·áºááá¯ááºáá«áááºá
ááŒá®ážáá»ááºááŒá®áž á¡á
áœááºážáááºáá±á¬áºáááºáž C++ áá²á·ááá¯á· ááá¯ááºááá¯ááºážáá±á¬áá¬áá¬á
áá¬ážááŒáá·áº REST API á¡ááá®áá±ážááŸááºážáá»á¬áž ááŒá¯á
á¯áá»áá¯ážáá±á¬ááºááẠáááºáá²áá±á¬áááºážááŒá±á¬ááºážáá±á«áºááœáẠá€áá¯á¶á
á¶áááááºááẠá
áááºáá°áá»á¬ážá¡ááœáẠáá°áá®áá±ážáááá·áºáááºáᯠáá»áŸá±á¬áºááá·áºáá«áááºá
ááá¯á·á¡ááŒáẠá€áá±áá¬ááœáẠáááºááŸá¯ááẠá¡áá°ážá¡ááŒá¶ááŒá¯ááá¯áá«áááºá
source: www.habr.com