{"id":49527999,"url":"https://github.com/yauntyour/appweb","last_synced_at":"2026-05-02T04:04:56.210Z","repository":{"id":43666753,"uuid":"511501865","full_name":"yauntyour/appweb","owner":"yauntyour","description":"appweb 开源执行端框架  具备集成的功能 性能极佳","archived":false,"fork":false,"pushed_at":"2026-03-31T05:25:16.000Z","size":9877,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-31T07:45:34.320Z","etag":null,"topics":["c","socket","webapp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yauntyour.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-07T11:33:42.000Z","updated_at":"2026-03-31T05:25:20.000Z","dependencies_parsed_at":"2025-07-29T07:05:32.766Z","dependency_job_id":"7e87f998-6a00-4b43-8ebf-85260cb49ba4","html_url":"https://github.com/yauntyour/appweb","commit_stats":null,"previous_names":[],"tags_count":4,"template":true,"template_full_name":null,"purl":"pkg:github/yauntyour/appweb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yauntyour%2Fappweb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yauntyour%2Fappweb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yauntyour%2Fappweb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yauntyour%2Fappweb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yauntyour","download_url":"https://codeload.github.com/yauntyour/appweb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yauntyour%2Fappweb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32522253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"online","status_checked_at":"2026-05-02T02:00:05.923Z","response_time":132,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","socket","webapp"],"created_at":"2026-05-02T04:04:18.504Z","updated_at":"2026-05-02T04:04:56.188Z","avatar_url":"https://github.com/yauntyour.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# appweb (v3.0)\n## ！⚠️新版的架构已经发布为servic.cpp和router.cpp\n具备简单的集成性基础功能。\n\u003c!--more--\u003e\n模块架构：\n\n- acc（接受请求）\n- rsc（响应+调度器实现）\n- RESRC（资源池）\u003chttps://github.com/yauntyour/RESRC\u003e\n- com（中心封装和集成）\n\n全部二次封装\u0026集成\u0026C++ class封装于`appweb.h`。\n\n## 详细内容\n\n### example.cpp dome\n\n```c\n#include \u003ciostream\u003e\n#include \u003cstdio.h\u003e\n#include \u003ctime.h\u003e\n#include \"appweb.h\"\n\nstatic RESRC res;\n\nFUNC_CB_C(api)\n{\n    printf(\"%s\\r\\n\", req-\u003edata.data);\n    return \"{'test':'Hello,World'}\";\n};\n\nFUNC_CB_C(POST_TEST)\n{\n#ifdef _WIN32\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"D:\\\\Dev\\\\appweb\\\\out\\\\post_test.html\");\n#else\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"/workspaces/appweb/out/post_test.html\");\n#endif\n    return p-\u003edata.data;\n};\n\nFUNC_CB_C(test)\n{\n    return \"\u003ch1 style='text-align:center;'\u003eHello,World\u003c/h1\u003e\";\n};\n\nFUNC_CB_C(img)\n{\n    // 在func内部使用send（）需要使用func_CB_OUT，因为需要一个“\\r\\n”字符来终止标头\n#ifdef _WIN32\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"D:\\\\Dev\\\\appweb\\\\out\\\\image.jpg\");\n#else\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"/workspaces/appweb/out/image.jpg\");\n#endif\n    FUNC_CB_OUT(req-\u003eaddr.socket, p-\u003edata.data, p-\u003edata.length, 0);\n    // 返回包含“\\0”是第一个字符的结果的字符串\n    return \"\";\n}\nvoid *func(void *arg)\n{\n#ifdef _WIN32\n    system(\"dir\");\n#else\n    system(\"ls -a\");\n#endif\n    return NULL;\n}\n\n#ifdef _WIN32\nstatic FILE_PATH file_list[] = {\n    {\"D:\\\\Dev\\\\appweb\\\\out\\\\post_test.html\", \"rb\"},\n    {\"D:\\\\Dev\\\\appweb\\\\out\\\\image.jpg\", \"rb\"},\n    {NULL, NULL}};\n#else\nstatic FILE_PATH file_list[] = {\n    {\"/workspaces/appweb/out/post_test.html\", \"rb\"},\n    {\"/workspaces/appweb/out/image.jpg\", \"rb\"},\n    {NULL, NULL}};\n#endif //_WIN32\n\nint main(int argc, char const *argv[])\n{\n    LOG_LIGHT_NF(\"%s\\n\", \"Build application by Yauntyour (https://github.com/yauntyour) with C++\");\n    RESRC_load_filelist(\u0026res, file_list, 2);\n#ifdef _WIN32\n    WS_Init();\n#endif\n    appweb app(8, 10000, 3);\n    app.set_root_dict_func(test, Type_ALL, \"text/html\");\n    Varde home_list[] = {\n        Varde_def(POST_TEST, Type_GET, \"postTest\", COMPATH_True, \"text/html\"),\n        Varde_def(api, Type_POST, \"api\", COMPATH_True, \"application/json\"),\n        Varde_def(img, Type_GET, \"img\", COMPATH_True, \"image/png\"),\n    };\n    Varde home_dict[] = {\n        {test, Type_GET, \"home\", home_list, 3, 3, COMPATH_True, \"text/html\"},\n        {test, Type_GET, \"index\", home_list, 3, 3, COMPATH_True, \"text/html\"}};\n    app.root_dict_p-\u003elist_append(home_dict, sizeof(home_dict) / sizeof(Varde));\n    app.root_dict_p-\u003eZIP();\n\n    app.add_event(func, NULL);\n    app.start(flag_wait);\n#ifdef _WIN32\n    WS_clean();\n#endif\n    for (size_t i = 0; file_list[i].path == NULL; i++)\n    {\n        RESRC_free(\u0026(res.filelist[i]));\n        RESRC_FILE_CLOSE(\u0026(res.filelist[i]));\n    }\n    return 0;\n}\n```\n\n### example.c dome\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003ctime.h\u003e\n#include \"appweb.h\"\n\nstatic RESRC res;\n\nFUNC_CB_C(api)\n{\n    printf(\"%s\\r\\n\", req-\u003edata.data);\n    return \"{'test':'Hello,World'}\";\n};\nFUNC_CB_C(POST_TEST)\n{\n#ifdef _WIN32\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"D:\\\\Dev\\\\appweb\\\\out\\\\post_test.html\");\n#else\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"/workspaces/appweb/out/post_test.html\");\n#endif\n    return p-\u003edata.data;\n};\nFUNC_CB_C(test)\n{\n    return \"\u003ch1 style='text-align:center;'\u003eHello,World\u003c/h1\u003e\";\n};\nFUNC_CB_C(img)\n{\n    // 在func内部使用send（）需要使用func_CB_OUT，因为需要一个“\\r\\n”字符来终止标头\n#ifdef _WIN32\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"D:\\\\Dev\\\\appweb\\\\out\\\\image.jpg\");\n#else\n    RESRC_FILE *p = RESRC_select_path(\u0026res, \"/workspaces/appweb/out/image.jpg\");\n#endif\n    FUNC_CB_OUT(req-\u003eaddr.socket, p-\u003edata.data, p-\u003edata.length, 0);\n    // 返回包含“\\0”是第一个字符的结果的字符串\n    return \"\";\n}\n\nvoid *func(void *arg)\n{\n#ifdef _WIN32\n    system(\"dir\");\n#else\n    system(\"ls -a\");\n#endif\n    return NULL;\n}\n\n#ifdef _WIN32\nstatic FILE_PATH file_list[] = {\n    {\"D:\\\\Dev\\\\appweb\\\\out\\\\post_test.html\", \"rb\"},\n    {\"D:\\\\Dev\\\\appweb\\\\out\\\\image.jpg\", \"rb\"},\n    {NULL, NULL}};\n#else\nstatic FILE_PATH file_list[] = {\n    {\"/workspaces/appweb/out/post_test.html\", \"rb\"},\n    {\"/workspaces/appweb/out/image.jpg\", \"rb\"},\n    {NULL, NULL}};\n#endif //_WIN32\n\nint main(int argc, char const *argv[])\n{\n    LOG_LIGHT_NF(\"%s\\n\", \"Build application by Yauntyour (https://github.com/yauntyour) with C\");\n    RESRC_load_filelist(\u0026res, file_list, 2);\n#ifdef _WIN32\n    WS_Init();\n#endif\n    appev_t ev;\n    ev.port = 10000;\n    ev.UTCoffset = 8;\n    // UDP_CONNECT or TCP_CONNECT\n    ev.connect_type = TCP_CONNECT; // Use TCP connection\n    // ev.connect_type = UDP_CONNECT;\n\n    app_event_init(\u0026ev, 128);\n\n    // root event\n    set_root_dict_func(\u0026ev, test, Type_ALL, \"text/html\");\n    // root list\n    ev.root_dict.list_length = 0;\n    ev.root_dict.list_size = 0;\n    ev.root_dict.list = NULL;\n\n    Varde home_list[] = {\n        Varde_def(POST_TEST, Type_GET, \"postTest\", COMPATH_True, \"text/html\"),\n        Varde_def(api, Type_POST, \"api\", COMPATH_True, \"application/json\"),\n        Varde_def(img, Type_GET, \"img\", COMPATH_True, \"image/png\"),\n    };\n    Varde home_dict[] = {\n        {test, Type_GET, \"home\", home_list, 3, 3, COMPATH_True, \"text/html\"},\n        {test, Type_GET, \"index\", home_list, 3, 3, COMPATH_True, \"text/html\"}};\n\n    Varde_list_append(\u0026(ev.root_dict), home_dict, sizeof(home_dict) / sizeof(Varde));\n    Varde_ZIP(\u0026(ev.root_dict));\n\n    // set a event func out of server\n    ev.event_func = func;\n\n    pthread_t acc_th;\n    app_acc(\u0026acc_th, \u0026ev);\n    pthread_join(acc_th, NULL);\n#ifdef _WIN32\n    WS_clean();\n#endif\n    for (size_t i = 0; file_list[i].path == NULL; i++)\n    {\n        RESRC_free(\u0026(res.filelist[i]));\n        RESRC_FILE_CLOSE(\u0026(res.filelist[i]));\n    }\n    return 0;\n}\n```\n\n\n\n### 基本使用\n\n Varde 的基本原理和结构————树级目录\n[![](tree.png)](Tree)\n\n1. 注册一个Varde，其结构为\n\n   ```C\n   /*\n           necessary arg:\n               char* Name :node's Name;\n               func_cb func :A deal by function;\n               int req_Type :request model;\n               struct varde *list :A node list this node;\n               size_t list_length, list_size :The list's length \u0026 size;\n               int ComPath :Common path resolution:true or false;\n           if req_model == -1,it will disable this Varde;\n          */\n       typedef struct varde\n       {\n           func_cb func;\n           int req_Type;\n           char *Name; // The Name of varde\n           struct varde *list;\n           size_t list_length;\n           size_t list_size;\n           int ComPath; // Common path resolution:true or false\n           char *resp_mime_type;\n   #ifdef __cplusplus\n           int append(struct varde *Var);\n           int ZIP();\n           int list_append(struct varde *dict, size_t len);\n   #endif //__cplusplus\n       } Varde;\n   \n   //函数类型为：\n   typedef char *(*func_cb)(req_t *, bytes *);\n   //利用该宏可以快速定义一个标准函数（参见example dome）\n   #define FUNC_CB_C(__name__) char *__name__(req_t *req, bytes *header)\n   //显然我们可以通过bytes组件库提供的操作函数为header添加内容。\n   //但是要注意，header尚未调用bytes_create。\n   //理论上根据规范，您只需要返回页面的内容，调度器会自动写入响应流的末尾。\n   \n   //如果你要在定义的FUNC_CB里使用内容输出：请使用这个宏\n   #define FUNC_CB_OUT(__arg__...) send(req-\u003eaddr.socket, \"\\r\\n\",2, 0);send(__arg__) \n   //就像这样：\n   FUNC_CB_C(img)\n   {\n       // 在func内部使用send（）需要使用func_CB_OUT，因为需要一个“\\r\\n”字符来终止标头\n       RESRC_FILE *p = RESRC_select_path(\u0026res, \"K:\\\\CCXXProgram\\\\appweb\\\\out\\\\bg.jpg\");\n       FUNC_CB_OUT(req-\u003eaddr.socket, p-\u003edata.data, p-\u003edata.length, 0);\n       // 返回包含“\\0”是第一个字符的结果的字符串\n       return \"\";\n   }\n   ```\n\n    我们提供一个快捷注册的宏\n\n    ```c++\n    #define Varde_def(func, req_Type, Name, ComPath)  \\\n        {                                             \\\n            func, req_Type, Name, NULL, 0, 0, ComPath \\\n        }\n    //eg: Varde var = Varde_def(test,req_ALL,\"test\",COMPATH_True);\n    ```\n\n   同时可以使用`append(struct varde *Var)`与`list_append(struct varde *dict, size_t len)`函数便捷地添加Varde节点或是直接追加Varde列表。\n\n   ```c++\n   app.set_root_dict_func(test, Type_ALL, \"text/html\");\n   Varde home_list[] = {\n   \tVarde_def(POST_TEST, Type_GET, \"postTest\", COMPATH_True, \"text/html\"),\n       Varde_def(api, Type_POST, \"api\", COMPATH_True, \"application/json\"),\n       Varde_def(img, Type_GET, \"img\", COMPATH_True, \"image/png\"),\n   };\n   Varde home_dict[] = {\n      \t{test, Type_GET, \"home\", home_list, 3, 3, COMPATH_True, \"text/html\"},\n       {test, Type_GET, \"index\", home_list, 3, 3, COMPATH_True, \"text/html\"}};\n   app.root_dict_p-\u003elist_append(home_dict, sizeof(home_dict) / sizeof(Varde));//追加列\n   app.root_dict_p-\u003eZIP();//删除冗余内存\n   ```\n\n   \n\n2. 使用`app.start(flag_wait);`执行服务。执行端会监听您提供的port。flag设置为0表示默认阻塞运行。\n\n3. 使用`app.add_event(func, NULL);`为程序添加额外的事件服务函数。\n\n   ```c++\n   void *func(void *arg)\n   {\n   #ifdef _WIN32\n       system(\"dir\");\n   #else\n       system(\"ls -a\");\n   #endif\n       return NULL;\n   }\n   app.add_event(func, NULL);//添加事件函数，会在acc线程执行后执行此线程\n   ```\n\n   可以在开启服务器的同时，额外注册一个线程执行自定义的内容，例如启动SQL服务、Python脚本等等。\n\n### 相关基础信息\n\n```c++\ntypedef struct appev\n{\n    IPv4_addr_t tcpip, udpip;\n    unsigned int port;\n    Varde root_dict;\n    size_t MAXCONNECT;\n    int UTCoffset;\n    int connect_type; // 0:TCP, 1:UDP, 2:ALL\n    void *(*event_func)(void *arg);//事件注册函数\n    void *arg;//参数指针\n    pthread_t event_th;\n} appev_t;\n```\n\n### SDK\u0026Debug\u0026Python实现的调试工具\n\n1. nc.py\n\n   ```python\n   #参数\n   if sys.argv[1] == '-nc':\n       netcat()\n   elif sys.argv[1] == '-cli':\n       UDPclientSend()\n   elif sys.argv[1] == '-server':\n       Server()\n   else:\n       print(\"no this mode\")\n       print(\"argv format: -mode host port recvbufflen/data (Server socketTypes:STREAM/DGRAM)\")\n   ##argv format: -mode host port recvbufflen/data (Server socketTypes:STREAM/DGRAM)\n   #eg :python nc.py -cli 127.0.0.1 10000 1280 STREAM\n   ```\n\n2. netools.py\n\n   ```python\n   #可以自行修改msg的内容\n   msg = \"GET /home HTTP/1.1\\r\\nHost: localhost\\r\\nUser-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2\\r\\n\\r\\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8\\r\\nAccept-Language: zh-cn,zh;q=0.5\\r\\nAccept-Encoding: gzip, deflate\\r\\nConnection: keep-alive\\r\\nReferer: http://localhost/\\r\\nContent-Length: 25\\r\\nContent-Type: application/x-www-form-urlencoded\\r\\nusername=aa\u0026password=1234\"\n   \n   if sys.argv[1] == '-nc':\n       netcat()\n   else:\n       print(\"argv format: -mode host port recvbufflen\")\n   #argv format: -mode host port recvbufflen\n   ```\n\n# 关键的依赖库\n\n## Windows下使用appweb库看起来这样（Windows下socket 需要 wsock32.lib）\n\n```\ng++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lwsock32 -lpthread\n```\n\n## Linux下使用appweb库看起来是这样的\n\n```\ng++ -g XXXX.cpp -o XXXX -fexec-charset=UTF-8 -lpthread\n```\n\n## 只需包含根目录下的appweb.h（C/C++完全封装）即可调用此库\n\n### **Made by yauntyour Copyright reserved**\n\n### e-mail:yauntyour@outlook.com\n\n### Copyright  see the file LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyauntyour%2Fappweb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyauntyour%2Fappweb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyauntyour%2Fappweb/lists"}