اس آرٹیکل میں میں اس بارے میں بات کروں گا کہ میں نے ٹیمپلیٹ (cookiecutter) کیسے بنایا اور docker/docker-compose اور conan پیکیج مینیجر کا استعمال کرتے ہوئے C++ میں REST API سروس لکھنے کے لیے ماحول قائم کیا۔
اگلے ہیکاتھون کے دوران، جس میں میں نے بیک اینڈ ڈویلپر کے طور پر حصہ لیا، سوال پیدا ہوا کہ اگلی مائیکرو سروس لکھنے کے لیے کیا استعمال کیا جائے۔ اب تک جو کچھ لکھا گیا ہے وہ سب میں نے اور میرا لکھا ہے۔
لہذا، ہمیں ایک ہائی لوڈ سروس لکھنے کے کام کا سامنا کرنا پڑا، جس کا بنیادی کام اس پر آنے والے ڈیٹا کو پہلے سے پروسیس کرنا اور اسے ڈیٹا بیس میں لکھنا تھا۔ اور ایک اور دھوئیں کے وقفے کے بعد، ایک دوست نے مشورہ دیا کہ میں، بطور C++ ڈویلپر، پیشہ کا استعمال کرتے ہوئے اس سروس کو لکھوں۔ اس کا استدلال یہ ہے کہ یہ تیز تر، زیادہ نتیجہ خیز ہوگا، اور عام طور پر، جیوری اس بات سے خوش ہوگی کہ ہم ٹیم کے وسائل کو کس طرح منظم کرنا جانتے ہیں۔ جس پر میں نے جواب دیا کہ میں نے C++ میں ایسی چیزیں کبھی نہیں کیں اور بقیہ 20+ گھنٹے آسانی سے موزوں لائبریریوں کو تلاش کرنے، مرتب کرنے اور لنک کرنے کے لیے وقف کر سکتا ہوں۔ سیدھے الفاظ میں ، میں نے چکن آؤٹ کیا۔ یہ وہی ہے جس پر ہم نے فیصلہ کیا اور سکون سے Python میں سب کچھ مکمل کیا۔
اب، جبری خود تنہائی کے دوران، میں نے یہ جاننے کا فیصلہ کیا کہ 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})
اس کے بعد، میں نے PostgreSQL کے ساتھ کام کرنے کے لیے ایک لائبریری کی تلاش شروع کی، کیونکہ یہ وہ تھی جس کے ساتھ مجھے کام کرنے کا بہت کم تجربہ تھا، اور یہ وہ تھی جس کے ساتھ ہماری Python سروسز نے بات چیت کی۔ اور کیا آپ جانتے ہیں کہ میں نے کیا سیکھا؟ یہ POCO میں ہے! لیکن کونن نہیں جانتا کہ یہ POCO میں ہے اور اسے نہیں معلوم کہ اسے کیسے بنایا جائے؛ ذخیرے میں ایک پرانی کنفیگریشن فائل ہے (میں اس غلطی کے بارے میں POCO کے تخلیق کاروں کو پہلے ہی لکھ چکا ہوں)۔ اس کا مطلب ہے کہ آپ کو دوسری لائبریری تلاش کرنی ہوگی۔
اور پھر میری پسند ایک کم مقبول لائبریری پر پڑی۔
اگلا مرحلہ ایک سروس ٹیمپلیٹ لکھنا تھا جو درخواستوں پر کارروائی کر سکے۔
ہمیں 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 کے ساتھ کام کرنے کے لیے ایک کلاس ٹیمپلیٹ بھی بنایا ہے۔ سادہ ایس کیو ایل کو انجام دینے کے لیے، جیسا کہ ٹیبل بنانا، ایک طریقہ ہے۔ 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 لکھنے کا آخری مرحلہ آتا ہے۔ سچ پوچھیں تو، اس میں زیادہ تر وقت لگا، اور نہ صرف اس لیے کہ میں ایک نوب ہوں، کیونکہ لائبریریوں کو ہر بار دوبارہ بنانا ضروری تھا، بلکہ کانن کے نقصانات کی وجہ سے۔ مثال کے طور پر، conan کے لیے ضروری انحصار کو ڈاؤن لوڈ، انسٹال اور بنانے کے لیے، اس کے لیے "conan install" ڈاؤن لوڈ کرنا کافی نہیں ہے، اسے -s compiler.libcxx=libstdc++11 پیرامیٹر کو بھی پاس کرنا ہوگا، بصورت دیگر آپ کو اپنی درخواست کو لنک کرنے کے مرحلے پر غلطیوں کا ایک گروپ ہونے کا خطرہ ہے۔ میں کئی گھنٹوں سے اس خرابی میں پھنسا ہوا ہوں اور مجھے امید ہے کہ یہ مضمون کم وقت میں اس مسئلے کو حل کرنے میں دوسرے لوگوں کی مدد کرے گا۔
اس کے بعد، docker-compose.yml لکھنے کے بعد، اپنے دوست کے مشورے پر، میں نے تعاون شامل کیا۔
مجھے امید ہے کہ یہ ٹیمپلیٹ شروع کرنے والوں کو REST API ایپلیکیشنز کو عظیم اور طاقتور، لیکن C++ جیسی اناڑی زبان میں تیار کرنے کے مشکل راستے پر مدد کرے گا۔
اس کے علاوہ، میں یہاں پڑھنے کی انتہائی سفارش کرتا ہوں۔
ماخذ: www.habr.com