Paozhu
Paozhu🧨 C++ Web Framework,(Based on C++20) Support HTTP/1 HTTP/2, Rapid development of CRUD web applications, Include modules HttpServer HttpClient WebSocket ORM
Install / Use
/learn @hggq/PaozhuREADME
English | 简体中文
<div align="center"> <img src="https://hggq.github.io/paozhu/images/logo.svg"> </div>Paozhu(炮竹🧨) is a comprehensive and fast C++ web framework that integrates C++ ORM. The development speed is as fast as script languages. The framework integrates a webserver, which can natively parse HTTP/1.1 HTTP/2 JSON WebSocket protocols and GET and POST requests. The framework also distinguishes between different methods of POST requests. The framework comes with a built-in OBJ micro-object that can store data such as char, int, string, float, etc. The framework automatically parses URL and POST parameters into the micro-object, and uses URL path mapping to function mounting points. It also uses coroutines, thread pools, and database connection pools.
QQ GROUP 668296235
Discussing the joy of C++ web development with community developers.
1.Features🔥🔥🔥🔥🔥
✅ 1. Support json decode encode, not use thirdparty, support json standard
✅ 2. Support multiple domain name websites
✅ 3. Support multiple domain name ssl server
✅ 4. Support http/1.1 and http/2 protocols
✅ 5. Support WebSocket server
✅ 6. The framework comes with websocket push, which supports regular push to websocket client
✅ 7. Support httpclient get or post
✅ 8. Built in ORM, currently only supports MySQL, providing coroutine and connection pooling functionality
✅ 9. Framework has two thread pool,framework thread pool,user program runing thread pool
✅10. The framework uses asio Coroutines
✅11. The framework features that I/O uses the coroutine pool to run and thread pool to run
✅12. The framework supports compress gzip br out files
✅13. URL POST Upload Files. use client.get[] client.post[] client.files[] get
✅14. Integrated sendmail
✅15. Generating QR code requires gd and qrencode libraries
✅16. Plugin module,Hot Module Replacement
✅17. The framework supports cache Module,ORM supports Result save to cache
✅18. The controller directory cpp files annotation auto pick to url mapping
✅19. Struct or class annotation to JSON Object, json_encode json_decode function
✅20. Support full demo admin backend, visit url /admin/main
✅21. Support PHP-FPM fastcgi running, which can replace Apache, allowing PHP programmers to smoothly transition to C++development mode
2.Runtime environment
C++ standard request c++20
asio openssl zlib brotli [options](gd qrencode)
Supports Linux MacOS Windows
3.environment configuration
3.1 MacOS
- system requirements
>= BigSur
- Install necessary dependencies
brew install asio
brew install cmake
brew install openssl
brew install zlib
brew install brotli
[options] brew install gd
[options] brew install qrencode
3.2 Ubuntu && Fedora
- system requirements
Ubuntu>= 22.04 , test on Fedora38, need install asan(sudo yum install libasan)
sudo apt-get install cmake
sudo apt-get install -y brotli libbrotli-dev zlib1g-dev
sudo apt-get install libgd-dev
sudo apt-get install qrencode libqrencode-dev
sudo apt-get install openssl libssl-dev
sudo apt-get install mysql-server
- Environment configuration
MacOS environment configuration
Ubuntu environment configuration
RockyLinux AlmaLinux environment configuration
3.3 Windows
Supports install methods vcpkg and xmake
- xmake install
Execute at the root directory of the project
Configconf/server.confreplace /Users/hzq/paozhu path to your project path
paozhu-main> xmake
paozhu-main> .\build\windows\x64\release\paozhu.exe
- vcpkg install
Invoke-WebRequest -OutFile vcpkg2023.zip https://github.com/microsoft/vcpkg/archive/refs/tags/2023.12.12.zip
unzip vcpkg2023.zip
cd vcpkg-2023.12.12
bootstrap-vcpkg.bat
vcpkg integrate install
vcpkg integrate project
vcpkg install
Install ninja https://github.com/ninja-build/ninja/releases
Compile project CMAKE_TOOLCHAIN_FILE is vcpkg install localtion path
unzip asio.zip
cmake . -B ${{github.workspace}} -DENABLE_WIN_VCPKG=ON -DENABLE_VCPKG=ON -DCMAKE_TOOLCHAIN_FILE=vcpkg-2023.12.12/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows -DCMAKE_BUILD_TYPE=Debug -G Ninja
cmake --build . --config Debug
4.Install
Project root unzip asio.zip or Download asio new version to project root part
|-vendor
|-CMakeLists.txt
|-asio
|-asio
|-asio.hpp
Directory like this
mkdir build
cd build
cmake ..
make
Use in production environment,Compile as daemon
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j8
5.hosts configuration
- view
conf/server.conffile and getmainhostvalue - replace /Users/hzq/paozhu path to your project path
- open host file
sudo vim /etc/hosts
Add to the last line of the hosts file (if it is www.869869.com)
127.0.0.1 www.869869.com
6.https test
run
sudo ./bin/paozhu
open the browser and enter http://localhost or http://www.869869.com in the address bar
for more details, please see the source code under the controller directory, which includes CRUD examples.
7.Stress testing
Use h2load and ab testing
ab -n 120000 -c 20 http://www.xxx.com
h2load -n 12000 -c 100 -m 10 https://www.xxx.com
./webbench -c 300 -t 59 http://www.xxx.com/cms/list
8.1 Sample Hello world
On controller directory ,testhello.cpp file
#include "orm.h"
#include "httppeer.h"
#include "testhello.h"
namespace http
{
//@urlpath(null,hello)
std::string testhello(std::shared_ptr<httppeer> peer)
{
httppeer &client = peer->get_peer();
client << " Hello world! 🧨 Paozhu c++ web framework ";
auto users = orm::cms::User();
try
{
users.where("name","admin").fetch_one();
if (users.getUserid() > 0)
{
client<<"<p>found:"<<users.data.name<<"</p>";
return "";
}
}
catch (std::exception &e)
{
client << "<p>" << e.what() << "</p>";
return "";
}
return "";
}
}// namespace http
Open the browser and enter http://localhost/hello
//@urlpath(null,hello) is annotation
8.2 Sample Article list,search,pagebar
From admin demo file controller/src/admin/articles.cpp
#include "orm.h"
#include <chrono>
#include <thread>
#include "httppeer.h"
#include "func.h"
#include "articles.h"
#include "json_reflect_headers.h"
#include "array_to_tree.h"
//@urlpath(admin_islogin,admin/listarticle)
std::string admin_listarticle(std::shared_ptr<httppeer> peer)
{
httppeer &client = peer->get_peer();
try
{
auto topicm = orm::cms::Topic();
topicm.where("userid", client.session["userid"].to_int()).asc("parentid").fetch();
unsigned int topicid = client.get["topicid"].to_int();
unsigned int page = client.get["page"].to_int();
std::string searchword = client.get["searchword"].to_string();
searchword = mb_substr(searchword, 0, 15);
client.val["topicid"] = topicid;
client.val["list"].set_array();
obj_val temp;
std::map<unsigned int, std::string> topickv;
std::vector<unsigned int> topic_id_array;//articles under this topic and sub topics
if (topicid > 0)
{
topic_id_array.push_back(topicid);
}
for (unsigned int i = 0; i < topicm.record.size(); i++)
{
temp["id"] = topicm.record[i].topicid;
temp["parentid"] = topicm.record[i].parentid;
temp["value"] = topicm.record[i].title;
client.val["list"].push(temp);
topickv[topicm.record[i].topicid] = topicm.record[i].title;
if (topicid > 0)
{
for (unsigned int j = 0; j < topic_id_array.size(); j++)
{
if (topicm.record[i].parentid == topic_id_array[j])
{
topic_id_array.push_back(topicm.record[i].topicid);
break;
}
}
}
}
auto artmodel = orm::cms::Article();
artmodel.where("userid", client.session["userid"].to_int());
if (topicid > 0)
{
std::string topicid_sql_str = array_to_sql(topic_id_array);
if (topicid_sql_str.size() > 0)
{
artmodel.whereIn("topicid", topicid_sql_str);
}
}
if (searchword.size() > 0)
{
artmodel.andsub().whereLike("title", str_addslash(searchword));
artmodel.whereOrLike("content", str_addslash(searchword)).andsub();
client.val["searchword"] = searchword;
}
auto [bar_min, bar_max, current_page, total_page] = artmodel.page(page, 10, 5);
client.val["pageinfo"].set_object();
client.val["pageinfo"]["min"] = bar_min;
client.val["pageinfo"]["max"] = bar_max;
client.val["pageinfo"]["current"] = current_page;
client.val["pageinfo"]["total"] = total_page;
artmodel.select("aid,topicid,title,createtime,sortid,isopen,ishome").desc("aid").fetch();
client.val["alist"].set_array();
obj_val tempa;
if (artmodel.size() > 0)
{
for (auto &item : artmodel)
{
tempa["title"] = item.title;
tempa["aid"] = item.aid;
tempa["date"] = item.createtime.substr(0, 10);
tempa["topicname"] = topickv[item.topicid];
tempa["sortid"] = item.sortid;
tempa["isopen"] = item.isopen;
tem
