English | çŽä˝ä¸ć
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. 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
C++ standard request c++20
asio openssl zlib brotli [options](gd qrencode)
- system requirements
>= BigSur
- Install necessary dependencies
brew install asio
brew install mysql
brew install openssl
brew install zlib
brew install brotli
[options] brew install gd
[options] brew install qrencode
- system requirements
Ubuntu>= 20.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
Noticeďź Requires gcc11 support. For more installation details, please see
- Environment configuration
paozhu linux environment configuration
Supports install methods vcpkg and xmake
- xmake install
Execute at the root directory of the project
Configconf/server.conf
replace /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
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
- view
conf/server.conf
file and getmainhost
value - 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
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.
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
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
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_ARRAY 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_array();
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").desc("aid").fetch();
client.val["alist"].set_array();
OBJ_ARRAY 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;
client.val["alist"].push(tempa);
}
}
}
catch (std::exception &e)
{
client.val["code"] = 1;
}
peer->view("admin/listarticle");
return "";
}
C++ ORM Coroutines,Only supports MySQL,URL request is completed throughout the entire coroutine function
From admin demo file controller/src/techempower.cpp
//@urlpath(null,updates)
asio::awaitable<std::string> techempowerupdates(std::shared_ptr<httppeer> peer)
{
peer->type("application/json; charset=UTF-8");
peer->set_header("Date", get_gmttime());
unsigned int get_num = peer->get["queries"].to_int();
if (get_num == 0)
{
get_num = 1;
}
else if (get_num > 500)
{
get_num = 500;
}
auto myworld = orm::World();
myworld.record.clear();
myworld.record.reserve(get_num);
for (unsigned int i = 0; i < get_num; i++)
{
myworld.wheresql.clear();
myworld.where("id", rand_range(1, 10000));
co_await myworld.async_fetch_append();
if (myworld.effect() > 0)
{
unsigned int j = myworld.record.size() - 1;
myworld.data.randomnumber = rand_range(1, 10000);
myworld.record[j].randomnumber = myworld.data.randomnumber;
co_await myworld.async_update("randomnumber");
}
}
peer->output = myworld.to_json();
co_return "";
}
- 1.Improved HTTP features
- 2.Use C++ parse JSX file , Server Side Rendering
- 3.Httpclient Improved,Support Protocol forwarding
- 4.Websocket client
- 5.HTTP/2 client
- 6.Postgres,sqlite ORM
welcome to raise issues for mutual communication, and of course, we also welcome your active PR.
Paozhu is provided under the MIT License