ืฉื™ืจื•ืชื™ ืžื™ืงืจื• ื‘-C++. ื‘ื“ื™ื” ืื• ืžืฆื™ืื•ืช?

ืฉื™ืจื•ืชื™ ืžื™ืงืจื• ื‘-C++. ื‘ื“ื™ื” ืื• ืžืฆื™ืื•ืช?

ื‘ืžืืžืจ ื–ื” ืื“ื‘ืจ ืขืœ ืื™ืš ื™ืฆืจืชื™ ืชื‘ื ื™ืช (Cookiecutter) ื•ื”ื’ื“ืจืชื™ ืกื‘ื™ื‘ื” ืœื›ืชื™ื‘ืช ืฉื™ืจื•ืช REST API ื‘-C++ ื‘ืืžืฆืขื•ืช docker/docker-compose ื•ืžื ื”ืœ ื”ื—ื‘ื™ืœื•ืช ืฉืœ conan.

ื‘ืžื”ืœืš ื”ื”ืืงืชื•ืŸ ื”ื‘ื, ื‘ื• ื”ืฉืชืชืคืชื™ ื›ืžืคืชื— ืื—ื•ืจื™, ืขืœืชื” ื”ืฉืืœื” ื‘ืžื” ืœื”ืฉืชืžืฉ ื›ื“ื™ ืœื›ืชื•ื‘ ืืช ื”ืžื™ืงืจื•-ืฉื™ืจื•ืช ื”ื‘ื. ื›ืœ ืžื” ืฉื ื›ืชื‘ ืขื“ ื›ื” ื ื›ืชื‘ ืขืœ ื™ื“ื™ ืฉืœื™ ื•ืฉืœื™ ื—ึธื‘ึตืจ ื‘-Python, ืžื›ื™ื•ื•ืŸ ืฉืขืžื™ืชื™ ื”ื™ื” ืžื•ืžื—ื” ื‘ืชื—ื•ื ื–ื” ื•ืคื™ืชื— ื’ื‘-ืื ื“ื™ื ืžืงืฆื•ืขื™, ื‘ืขื•ื“ ืฉื‘ื“ืจืš ื›ืœืœ ื”ื™ื™ืชื™ ืžืคืชื— ืžืขืจื›ื•ืช ืžืฉื•ื‘ืฆื•ืช ื•ื›ืชื‘ืชื™ ื‘-C++ ื”ื ื”ื“ืจ ื•ื”ื ื•ืจื, ื•ื‘ื“ื™ื•ืง ืœืžื“ืชื™ Python ื‘ืื•ื ื™ื‘ืจืกื™ื˜ื”.

ืœื›ืŸ, ืขืžื“ื” ื‘ืคื ื™ื ื• ื”ืžืฉื™ืžื” ืฉืœ ื›ืชื™ื‘ืช ืฉื™ืจื•ืช ื‘ืขื•ืžืก ื’ื‘ื•ื”, ืฉืขื™ืงืจ ื”ืžืฉื™ืžื” ืฉืœื• ื”ื™ื™ืชื” ืœืขื‘ื“ ืžืจืืฉ ืืช ื”ื ืชื•ื ื™ื ื”ืžื’ื™ืขื™ื ืืœื™ื• ื•ืœื›ืชื•ื‘ ืื•ืชื ืœืžืกื“ ื”ื ืชื•ื ื™ื. ื•ืื—ืจื™ ื”ืคืกืงืช ืขืฉืŸ ื ื•ืกืคืช, ื—ื‘ืจ ื”ืฆื™ืข ืœื™, ื›ืžืคืชื— C++, ืœื›ืชื•ื‘ ืืช ื”ืฉื™ืจื•ืช ื”ื–ื” ื‘ืืžืฆืขื•ืช ื”ืžืงืฆื•ืขื ื™ื. ื‘ื˜ืขื ื” ืฉื–ื” ื™ื”ื™ื” ืžื”ื™ืจ ื™ื•ืชืจ, ืคืจื•ื“ื•ืงื˜ื™ื‘ื™ ื™ื•ืชืจ, ื•ื‘ืื•ืคืŸ ื›ืœืœื™, ื—ื‘ืจ ื”ืžื•ืฉื‘ืขื™ื ื™ืฉืžื— ืžื”ืื•ืคืŸ ืฉื‘ื• ืื ื—ื ื• ื™ื•ื“ืขื™ื ืœื ื”ืœ ืืช ืžืฉืื‘ื™ ื”ืฆื•ื•ืช. ืขืœ ื›ืš ืขื ื™ืชื™ ืฉืžืขื•ืœื ืœื ืขืฉื™ืชื™ ื“ื‘ืจื™ื ื›ืืœื” ื‘-C++ ื•ื™ื›ื•ืœืชื™ ื‘ืงืœื•ืช ืœื”ืงื“ื™ืฉ ืืช 20+ ื”ืฉืขื•ืช ื”ื ื•ืชืจื•ืช ืœื—ื™ืคื•ืฉ, ื”ื™ื“ื•ืจ ื•ืงื™ืฉื•ืจ ืกืคืจื™ื•ืช ืžืชืื™ืžื•ืช. ื‘ืžื™ืœื™ื ืคืฉื•ื˜ื•ืช, ื”ืฉืชื—ืจืจืชื™. ื–ื” ืžื” ืฉื”ื—ืœื˜ื ื• ื•ื”ืฉืœืžื ื• ื”ื›ืœ ื‘ืคื™ื™ืชื•ืŸ ื‘ืฉืœื•ื•ื”.

ื›ืขืช, ื‘ืžื”ืœืš ื”ื‘ื™ื“ื•ื“ ื”ืขืฆืžื™ ื”ื›ืคื•ื™, ื”ื—ืœื˜ืชื™ ืœื”ื‘ื™ืŸ ื›ื™ืฆื“ ืœื›ืชื•ื‘ ืฉื™ืจื•ืชื™ื ื‘-C++. ื”ื“ื‘ืจ ื”ืจืืฉื•ืŸ ืฉืฆืจื™ืš ืœืขืฉื•ืช ื”ื™ื” ืœื”ื—ืœื™ื˜ ืขืœ ืกืคืจื™ื™ื” ืžืชืื™ืžื”. ื”ื‘ื—ื™ืจื” ืฉืœื™ ื ืคืœื” ืขืœ POCO, ืฉื›ืŸ ื”ื•ื ื ื›ืชื‘ ื‘ืกื’ื ื•ืŸ ืžื•ื ื—ื” ืขืฆืžื™ื ื•ื”ืชื”ื“ืจ ื’ื ื‘ืชื™ืขื•ื“ ืจื’ื™ืœ. ื›ืžื• ื›ืŸ, ืขืœืชื” ื”ืฉืืœื” ืœื’ื‘ื™ ื‘ื—ื™ืจืช ืžืขืจื›ืช ื”ืจื›ื‘ื”. ืขื“ ืœื ืงื•ื“ื” ื–ื• ืขื‘ื“ืชื™ ืจืง ืขื Visual Studio, IAR ื•-makefiles ื—ืฉื•ืคื™ื. ื•ืืฃ ืื—ืช ืžื”ืžืขืจื›ื•ืช ื”ืœืœื• ืœื ืžืฆืื” ื—ืŸ ื‘ืขื™ื ื™ื™, ืžื›ื™ื•ื•ืŸ ืฉืชื›ื ื ืชื™ ืœื”ืคืขื™ืœ ืืช ื›ืœ ื”ืฉื™ืจื•ืช ื‘ืžื™ื›ืœ ื“ื•ืงืจ. ื•ืื– ื”ื—ืœื˜ืชื™ ืœื ืกื•ืช ืœื”ื‘ื™ืŸ cmake ื•ืžื ื”ืœ ื—ื‘ื™ืœื•ืช ืžืขื ื™ื™ืŸ ืงื•ื ืืŸ. ืžื ื”ืœ ื”ื—ื‘ื™ืœื•ืช ื”ื–ื” ืืคืฉืจ ืœืš ืœืจืฉื•ื ืืช ื›ืœ ื”ืชืœื•ืช ื‘ืงื•ื‘ืฅ ืื—ื“

conanfile.txt
[ื“ื•ืจืฉ]poco/1.9.3
libpq/11.5

[ื’ื ืจื˜ื•ืจื™ื] cmeke

ื•ืขื ืคืงื•ื“ื” ืคืฉื•ื˜ื” "conan install ." ืœื”ืชืงื™ืŸ ืืช ื”ืกืคืจื™ื•ืช ื”ื“ืจื•ืฉื•ืช. ืžื˜ื‘ืข ื”ื“ื‘ืจื™ื, ื”ื™ื” ืฆื•ืจืš ื’ื ืœื‘ืฆืข ืฉื™ื ื•ื™ื™ื ื‘

CMakeLists.txt

include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})

ืœืื—ืจ ืžื›ืŸ, ื”ืชื—ืœืชื™ ืœื—ืคืฉ ืกืคืจื™ื™ื” ืœืขื‘ื•ื“ื” ืขื PostgreSQL, ืžื›ื™ื•ื•ืŸ ืฉื–ื• ื”ื™ื™ืชื” ื”ืกืคืจื™ื™ื” ืฉืื™ืชื” ื”ื™ื” ืœื™ ื ื™ืกื™ื•ืŸ ืžื•ืขื˜ ื‘ืขื‘ื•ื“ื”, ื•ื”ื™ื ื’ื ื–ื• ืฉืฉื™ืจื•ืชื™ Python ืฉืœื ื• ื™ืฆืจื• ืื™ืชื” ืื™ื ื˜ืจืืงืฆื™ื”. ื•ืืชื” ื™ื•ื“ืข ืžื” ืœืžื“ืชื™? ื–ื” ื‘-POCO! ืื‘ืœ conan ืœื ื™ื•ื“ืข ืฉื–ื” ื‘-POCO ื•ืœื ื™ื•ื“ืข ืื™ืš ืœื‘ื ื•ืช ืืช ื–ื”, ื™ืฉ ืงื•ื‘ืฅ ืงื•ื ืคื™ื’ื•ืจืฆื™ื” ืžื™ื•ืฉืŸ ื‘ืžืื’ืจ (ื›ื‘ืจ ื›ืชื‘ืชื™ ืขืœ ื”ืฉื’ื™ืื” ื”ื–ื• ืœื™ื•ืฆืจื™ POCO). ื–ื” ืื•ืžืจ ืฉืชืฆื˜ืจืš ืœื—ืคืฉ ืกืคืจื™ื™ื” ืื—ืจืช.

ื•ืื– ื”ื‘ื—ื™ืจื” ืฉืœื™ ื ืคืœื” ืขืœ ืกืคืจื™ื™ื” ืคื—ื•ืช ืคื•ืคื•ืœืจื™ืช libpg. ื•ื”ื™ื” ืœื™ ืžื–ืœ ืžื“ื”ื™ื, ื–ื” ื›ื‘ืจ ื”ื™ื” ื‘ืงื•ื ืืŸ ื•ืืคื™ืœื• ื”ื™ื” ื‘ื”ืจื›ื‘ื” ื•ื”ืจื›ื‘ื”.

ื”ืฉืœื‘ ื”ื‘ื ื”ื™ื” ืœื›ืชื•ื‘ ืชื‘ื ื™ืช ืฉื™ืจื•ืช ืฉื™ื›ื•ืœื” ืœืขื‘ื“ ื‘ืงืฉื•ืช.
ืขืœื™ื ื• ืœืจืฉืช ืืช ื”ืžื—ืœืงื” TemplateServerApp ืฉืœื ื• ืž-Poco::Util::ServerApplication ื•ืœืขืงื•ืฃ ืืช ื”ืฉื™ื˜ื” ื”ืจืืฉื™ืช.

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() ื•ื”ืฉืชืžืฉ ื‘ืžืžืฉืง ื”-API ืฉืœ libpg. (ืื•ืœื™ ืื—ืจ ื›ืš ืืชืงืŸ ืืช ื”ืขื•ื•ืœ ื”ื–ื”).

ืžืกื“ ื ืชื•ื ื™ื

#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

.v

DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432

ืืชื” ื™ื›ื•ืœ ืœืจืื•ืช ืืช ื›ืœ ื”ืงื•ื“ ื‘ github.

ืฉื™ืจื•ืชื™ ืžื™ืงืจื• ื‘-C++. ื‘ื“ื™ื” ืื• ืžืฆื™ืื•ืช?

ื•ืขื›ืฉื™ื• ืžื’ื™ืข ื”ืฉืœื‘ ื”ืื—ืจื•ืŸ ืฉืœ ื›ืชื™ื‘ืช ื”- dockerfile ื•- docker-compose.yml. ืœืžืขืŸ ื”ืืžืช, ื–ื” ืœืงื— ืืช ืจื•ื‘ ื”ื–ืžืŸ, ื•ืœื ืจืง ื‘ื’ืœืœ ืฉืื ื™ ื ื•ื‘, ื›ื™ ื”ื™ื” ืฆื•ืจืš ืœื‘ื ื•ืช ืžื—ื“ืฉ ืืช ื”ืกืคืจื™ื•ืช ื‘ื›ืœ ืคืขื, ืืœื ื‘ื’ืœืœ ื”ืžืœื›ื•ื“ื•ืช ืฉืœ ืงื•ื ืืŸ. ืœื“ื•ื’ืžื”, ื›ื“ื™ ืฉ-conan ื™ื•ื›ืœ ืœื”ื•ืจื™ื“, ืœื”ืชืงื™ืŸ ื•ืœื‘ื ื•ืช ืืช ื”ืชืœื•ืช ื”ื ื“ืจืฉืช, ื–ื” ืœื ืžืกืคื™ืง ื›ื“ื™ ืœื”ื•ืจื™ื“ ืืช "conan install .", ื”ื•ื ืฆืจื™ืš ื’ื ืœื”ืขื‘ื™ืจ ืืช ื”ืคืจืžื˜ืจ -s compiler.libcxx=libstdc++11, ืื—ืจืช ืืชื” ืžืกืชื›ืŸ ื‘ืงื‘ืœืช ืฉืœืœ ืฉื’ื™ืื•ืช ื‘ืฉืœื‘ ื”ืงื™ืฉื•ืจ ืฉืœ ื”ื™ื™ืฉื•ื ืฉืœืš. ืื ื™ ืชืงื•ืข ืขื ื”ืฉื’ื™ืื” ื”ื–ื• ื›ื‘ืจ ื›ืžื” ืฉืขื•ืช ื•ืื ื™ ืžืงื•ื•ื” ืฉืžืืžืจ ื–ื” ื™ืขื–ื•ืจ ืœืื ืฉื™ื ืื—ืจื™ื ืœืคืชื•ืจ ืืช ื”ื‘ืขื™ื” ื‘ืคื—ื•ืช ื–ืžืŸ.

ืœืื—ืจ ืžื›ืŸ, ืœืื—ืจ ืฉื›ืชื‘ืชื™ docker-compose.yml, ื‘ืขืฆืช ื—ื‘ืจื™, ื”ื•ืกืคืชื™ ืชืžื™ื›ื” ื—ื•ืชื›ืŸ ืขื•ื’ื™ื•ืช ื•ืขื›ืฉื™ื• ืืชื” ื™ื›ื•ืœ ืœื”ืฉื™ื’ ืœืขืฆืžืš ืชื‘ื ื™ืช ืžืœืื” ืขื‘ื•ืจ ืฉื™ืจื•ืช REST API ื‘-C++, ืขื ืกื‘ื™ื‘ื” ืžื•ืชืืžืช, ื•-PostgreSQL ืžื•ืชืงืŸ, ืคืฉื•ื˜ ืขืœ ื™ื“ื™ ื”ื–ื ืช "Cookiecutter" ื‘ืงื•ื ืกื•ืœื” https://github.com/KovalevVasiliy/cpp_rest_api_template.git" ื•ืื– "ื“ื•ืงืจ-compose up - build".

ืื ื™ ืžืงื•ื•ื” ืฉื”ืชื‘ื ื™ืช ื”ื–ื• ืชืขื–ื•ืจ ืœืžืชื—ื™ืœื™ื ื‘ื“ืจืš ื”ืงืฉื” ืฉืœื”ื ืœืคื™ืชื•ื— ื™ื™ืฉื•ืžื™ REST API ื‘ืฉืคื” ื”ื ื”ื“ืจืช ื•ื”ื—ื–ืงื”, ืื‘ืœ ื›ืœ ื›ืš ืžื’ื•ืฉืžืช ื›ืžื• C++.
ื›ืžื• ื›ืŸ, ืื ื™ ืžืžืœื™ืฅ ื‘ื—ื•ื ืœืงืจื•ื ื›ืืŸ ื–ื” ืžืืžืจ. ื”ื•ื ืžืกื‘ื™ืจ ื‘ื™ืชืจ ืคื™ืจื•ื˜ ื›ื™ืฆื“ ืœืขื‘ื•ื“ ืขื POCO ื•ืœื›ืชื•ื‘ ืฉื™ืจื•ืช REST API ืžืฉืœืš.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”