هن آرٽيڪل ۾ آئون انهي بابت ڳالهائيندس ته مون هڪ ٽيمپليٽ (cookiecutter) ڪيئن ٺاهيو ۽ سي ++ ۾ هڪ REST API سروس لکڻ لاءِ ماحول قائم ڪيو docker/docker-compose ۽ conan پيڪيج مئنيجر استعمال ڪندي.
ايندڙ هيڪاٿون دوران، جنهن ۾ مون هڪ پس منظر ڊولپر جي حيثيت ۾ حصو ورتو، سوال اڀريو ته ايندڙ مائڪرو سروس لکڻ لاءِ ڇا استعمال ڪجي. هن وقت تائين جيڪو ڪجهه لکيو ويو آهي اهو سڀ ڪجهه منهنجي ۽ منهنجي طرفان لکيو ويو آهي
تنهن ڪري، اسان کي هڪ اعلي-لوڊ سروس لکڻ جي ڪم سان منهن ڏيڻو پيو، جنهن جو بنيادي ڪم اهو هو ته ڊيٽا کي اڳڀرائي ڪرڻ ۽ ان کي ڊيٽابيس ۾ لکڻ. ۽ هڪ ٻي تماڪ جي وقفي کان پوءِ، هڪ دوست صلاح ڏني ته مان، هڪ C++ ڊولپر جي حيثيت سان، هن خدمت کي استعمال ڪندي لکان. دليل ڏيڻ اهو آهي ته اهو تيز، وڌيڪ پيداوار وارو، ۽ عام طور تي، جوري خوش ٿيندو ته اسان ڪيئن ڄاڻون ٿا ته ٽيم جي وسيلن کي ڪيئن منظم ڪجي. جنهن تي مون جواب ڏنو ته مون اهڙيون شيون ڪڏهن به C++ ۾ نه ڪيون آهن ۽ باقي 20+ ڪلاڪ آسانيءَ سان مناسب لائبريرين کي ڳولڻ، مرتب ڪرڻ ۽ ڳنڍڻ لاءِ وقف ڪري سگهندس. آسانيءَ سان، مون ڪڪڙ ڪڍي ڇڏيو. اھو اھو آھي جيڪو اسان فيصلو ڪيو ۽ آرام سان پٿون ۾ سڀ ڪجھ مڪمل ڪيو.
ھاڻي، زبردستي خود اڪيلائي دوران، مون اھو معلوم ڪرڻ جو فيصلو ڪيو ته C++ ۾ خدمتون ڪيئن لکجي. ڪرڻ جو پهريون ڪم هڪ مناسب لائبريري تي فيصلو ڪيو ويو. منهنجي پسند تي اچي ويو
conanfile.txt
پوڪو/1.9.3
libpq/11.5
۽ هڪ سادي حڪم سان "conan install." ضروري لائبريرين کي انسٽال ڪريو. قدرتي طور تي، ان ۾ تبديليون پڻ ضروري هئي
CMakeLists.txt
include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})
ان کان پوء، مون پوسٽ گري ايس ايس ايل سان ڪم ڪرڻ لاء هڪ لائبريري ڳولڻ شروع ڪيو، ڇاڪاڻ ته اها هڪ هئي جنهن سان مون کي ڪم ڪرڻ جو ٿورو تجربو هو، ۽ اهو پڻ هو ته اسان جي پٿون خدمتن سان رابطو ڪيو. ۽ توهان کي خبر آهي ته مون ڇا سکيو؟ اهو POCO ۾ آهي! پر ڪنن کي خبر ناهي ته اهو 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(). وڌيڪ پيچيده سوالن يا ڊيٽا حاصل ڪرڻ لاء، توهان کي حاصل ڪرڻو پوندو ذريعي ڪنيڪشن ڪنيڪشن حاصل ڪريو () ۽ 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. سچ پڇو، اهو گهڻو وقت وٺندو آهي، ۽ نه صرف ان ڪري جو مان هڪ نوب آهيان، ڇاڪاڻ ته اهو ضروري هو ته لائبريرين کي هر وقت ٻيهر تعمير ڪيو وڃي، پر ڪنن جي نقصانن جي ڪري. مثال طور، ڪانن کي ڊائون لوڊ ڪرڻ، انسٽال ڪرڻ ۽ ضروري انحصار ٺاهڻ لاءِ، ان لاءِ ”ڪونان انسٽال“ ڊائون لوڊ ڪرڻ ڪافي ناهي، ان کي پڻ پاس ڪرڻ جي ضرورت آهي -s compiler.libcxx=libstdc++11 پيٽرول، ٻي صورت ۾. توهان کي توهان جي ايپليڪيشن کي ڳنڍڻ واري مرحلي ۾ غلطين جو هڪ گروپ حاصل ڪرڻ جو خطرو آهي. مان ڪيترن ئي ڪلاڪن کان هن غلطي سان بيٺو آهيان ۽ اميد اٿم ته هي آرٽيڪل ٻين ماڻهن کي گهٽ وقت ۾ هن مسئلي کي حل ڪرڻ ۾ مدد ڪندو.
اڳيون، docker-compose.yml لکڻ کان پوء، منهنجي دوست جي صلاح تي، مون سپورٽ شامل ڪيو
مون کي اميد آهي ته هي ٽيمپليٽ نئين سکندڙن کي وڏي ۽ طاقتور ۾ REST API ايپليڪيشنن کي ترقي ڪرڻ جي مشڪل رستي تي مدد ڪندي، پر اهڙي بيڪار ٻولي جهڙوڪ C++.
انهي سان گڏ، آئون هتي پڙهڻ جي سفارش ڪريان ٿو
جو ذريعو: www.habr.com