{"id":23801918,"url":"https://github.com/lord-turmoil/minet-core","last_synced_at":"2026-06-30T10:31:30.227Z","repository":{"id":269167000,"uuid":"891904823","full_name":"Lord-Turmoil/minet-core","owner":"Lord-Turmoil","description":"Mini HTTP server library from scratch with C++","archived":false,"fork":false,"pushed_at":"2025-01-10T08:28:45.000Z","size":199,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-11T10:31:53.460Z","etag":null,"topics":["epoll-tcp-server","http","http-server","http-server-library","thread-pool"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Lord-Turmoil.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":"2024-11-21T06:57:13.000Z","updated_at":"2025-01-11T12:55:15.000Z","dependencies_parsed_at":"2024-12-21T13:25:30.565Z","dependency_job_id":"8893bcf5-6de4-4da8-8306-4a6715cd7412","html_url":"https://github.com/Lord-Turmoil/minet-core","commit_stats":null,"previous_names":["lord-turmoil/minet-core"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Lord-Turmoil/minet-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Turmoil%2Fminet-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Turmoil%2Fminet-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Turmoil%2Fminet-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Turmoil%2Fminet-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Lord-Turmoil","download_url":"https://codeload.github.com/Lord-Turmoil/minet-core/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lord-Turmoil%2Fminet-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34963632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"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":["epoll-tcp-server","http","http-server","http-server-library","thread-pool"],"created_at":"2025-01-01T22:15:57.361Z","updated_at":"2026-06-30T10:31:30.206Z","avatar_url":"https://github.com/Lord-Turmoil.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# minet core\n\n\u003e A C++ HTTP server library mimicking ASP.NET Core\n\u003e\n\u003e Copyright \u0026copy; 2024 Tony's Studio\n\n---\n\n[![Build-and-Test](https://github.com/Lord-Turmoil/minet-core/actions/workflows/build-and-test.yml/badge.svg?branch=main)](https://github.com/Lord-Turmoil/minet-core/actions/workflows/build-and-test.yml)\n\n# Prologue\n\n**minet core** is a C++ HTTP server library that mimics the design of ASP.NET Core. It is designed to be a lightweight, high-performance, and easy-to-use library for building web applications in C++.\n\n\u003e [!IMPORTANT]\n\u003e Currently, this library only targets Linux platforms. It is not the library you are looking for if you want cross-platform support.\n\n## Features\n\nAlthough **minet core** is simple, it indeed has some cool features.😎\n\n- **Easy to Use**: It is super easy to create a server with just a few lines of code.\n- **Flexible Configuration**: You can configure the server with a JSON file.\n- **Dependency Injection**: It uses IoC to manage components, and you can replace them with your own.\n- **Multiple Servers**: It provides multiple server implementations, good for study and comparison.\n- **Extensible**: It is designed to be extensible, and you can build your framework on top of it.\n\n## Purpose\n\nThe main purpose for **minet core** is to learn the mechanism behind an HTTP server. The key is to understand how the server accepts and handles requests, and how it sends responses back. It is also a good practice to learn how to design a library that is easy to use and flexible to extend.\n\n## Key Points\n\nThe most important part of **minet core** is the design of the server. The server is responsible for accepting requests. As my knowledge expands, I have implemented three different servers.\n\nThe first is `Basic` server, accepting requests in one thread. It is simple and easy to understand, but it is not efficient.\n\nThe second is `Threaded` server, which handles requests in multiple threads with a thread pool.\nIt is way more efficient than the `Basic` server, but it is not the best.\n\nThe third is `Mayhem` server, based on `Threaded` server, but also utilizes epoll for asynchronous I/O. It is the most efficient server in **minet core**.\n\n---\n\n# Getting Started\n\n\u003e [!NOTE]\n\u003e Before you move on, ensure you have CMake and your C++ compiler supports C++ 17.🫡\n\n\u003e [!WARNING]\n\u003e If you build **minet-core** with TSan (Thread Sanitizer) on Ubuntu 20.04, you may get linker error saying missing `libtsan_preinit.o`. Check [(TSAN) /usr/bin/ld can't find libtsan_preinit.o](https://stackoverflow.com/questions/77858687/tsan-usr-bin-ld-cant-find-libtsan-preinit-o) for solutions.\n\n## Prepare the Repository\n\n**minet-core** relies on some third-party libraries, you can clone it with the following command.\n\n```bash\ngit clone https://github.com/Lord-Turmoil/minet-core.git --recurse-submodules\n```\n\nOr, you can clone it first, and then update the submodules.\n\n```bash\ngit clone https://github.com/Lord-Turmoil/minet-core.git\ncd minet-core\ngit submodule update --init --recursive\n```\n\nIf you want to update the submodules, you can run the following command, or `./script/update.sh`.\n\n```bash\ngit submodule update --recursive\n```\n\n## Build the Library\n\n\u003e [!NOTE]\n\u003e By default, the sanitizer options are OFF. You can enable address sanitizer or thread sanitizer by enabling `MINET_ASAN` or `MINET_TSAN` option respectively. Since these two sanitizers are not compatible with each other, TSan will be ignored if ASan is enabled.\n\n### Have a try\n\nBefore you decide to use **minet-core** in your project, you can build the demo server to see how it works. The following commands will build libray and the demo server. You can also jump to the following section to see the bundled demo.\n\n```bash\n./script/build.sh debug   # build the debug version\n./script/build.sh release # build the release version\n```\n\n### Use it in your project\n\nTo use **minet core** in your project, simply add it as a subdirectory in your CMake project. Then link your target with `minetcore`.\n\n```cmake\nadd_subdirectory(\"minet-core\")\ntarget_link_libraries(your-app-name PRIVATE minetcore)\n```\n\n## Your First Server\n\nIt is super easy to create a server with **minet-core**, just a few lines of code and you are ready to go.😆\n\n```cpp\n#include \u003cminet/minet.h\u003e\n\nusing namespace minet;\n\nint main()\n{\n    WebHostBuilder::Create()\n        -\u003eUseAppSettings()\n        -\u003eGet(\"/ping\", RequestHandler::Bind(\n            [](const TextRequest\u0026 request, TextResponse\u0026 response) {\n                response.Text().assign(\"pong\"); \n            }))\n        -\u003eBuild()\n        -\u003eRun();\n    return 0;\n}\n```\n\n\u003e [!CAUTION]\n\u003eFor now, there is a known issue in this calling chain. You have to call `UseAppSettings()` (with or without parameter) before you call any other functions. It loads settings and initializes necessary components.😢\n\n## The Demo\n\nThe example above might be a little too simple. For a more comprehensive demonstration, you can see the demo server under `demo/`. To see it live, use the following commands. It will run the demo server, and send some dummy requests to it. There are two server options available. And the client will launch 4 processes to send requests at the same time.\n\n```bash\n# build and run the demo server\n./script/demo.sh server        # run with Basic server\n./script/demo.sh server mayhem # run with Mayhem server\n\n# in another terminal\n./script/demo.sh client        # 4 processes, each sending 10 requests\n./script/demo.sh client N      # 4 processes, each sending N requests\n./script/demo.sh client N M    # 2^M processes, each sending N requests\n```\n\nBasic server handles requests in one thread, so you'll see the client return one response at a time. Mayhem server handles requests asynchronously, so you'll see a significant speedup in the client.\n\nThe configuration files are also provided in `demo/`, you can modify them to see the effects.\n\n\u003e [!TIP]\n\u003eBy default, the server launch at `http://localhost:5000`, so make sure this port isn't blocked or occupied. And the demo client uses `curl` to send requests.\n\n---\n\n# Endpoints\n\n## Request/Response Wrapper\n\nTo relieve you from the tedious work of serializing and deserializing requests and responses, **minet-core** provides a wrapper for them. You can access the request and response via `TextRequest` and `TextResponse` for text-based content, or `JsonRequest` and `JsonResponse` for JSON content.\n\n`TextRequest`/`TextResponse` provides `Text()` method to access the plain text body. `JsonRequest`/`JsonResponse` provides `Json()` method to access the JSON body. You can also use `Headers()` to access the headers, and `Params()` to access the query parameters.\n\n## Request Handler\n\nRequest handler is where you write the server logic. It takes the request and response as parameters as shown below. `TRequest` and `TResponse` are template types for the wrapper.\n\n```cpp\nusing RequestHandlerFn = std::function\u003cvoid(const TRequest\u0026, TResponse\u0026)\u003e;\n```\n\n**minet-core** provides a convenient way to create request handlers by using predefined templates. For plain text request and response, you can use `RequestHandler` directly. For JSON request and response, you can use `RestfulHandler`. If request and response types are different, you can use `CustomHandler` instead. Below are their definitions.\n\n```cpp\nusing RequestHandler = RequestHandlerImpl\u003cTextRequest, TextResponse\u003e;\nusing RestfulHandler = RequestHandlerImpl\u003cJsonRequest, JsonResponse\u003e;\ntemplate \u003ctypename TRequest, typename TResponse\u003e\nusing CustomHandler = RequestHandlerImpl\u003cTRequest, TResponse\u003e;\n```\n\n```cpp\nvoid text(const TextRequest\u0026 request, TextResponse\u0026 response);\nvoid json(const JsonRequest\u0026 request, JsonResponse\u0026 response);\nvoid custom(const TextRequest\u0026 request, JsonResponse\u0026 response);\n\n// create WebHostBuilder\n\nbuilder\n    -\u003eGet(\"/text\", RequestHandler::Bind(text))\n    -\u003ePost(\"/json\", RestfulHandler::Bind(json))\n    -\u003ePost(\"/custom\", CustomHandler::Bind(custom));\n```\n\nSee, isn't it easy?😉\n\n---\n\n# Configuration\n\n**minet-core** provides flexible configurations for your server. By default, it will load configurations from `appsettings.json` in the working directory. You can change it by passing custom path to `UseAppSeettings()` function, just like what you see in the demo server.\n\nThe configuration file should be in JSON format, and comments are allowed. All settings in the configuration file are optional, so it can be as simple as `{}`. There are two built-in settings for **minet-core**, `server` and `logging`, and you can add extra settings.\n\n## Settings\n\n### Server\n\nThe server settings include the `name` of the server, and the `port` to listen on.\n\n```json\n{\n    \"server\": {\n        \"name\": \"Basic\",\n        \"threads\": 4,\n        \"capacity\": 1024,\n        \"port\": 5000\n    }\n}\n```\n\nNotably, `name` specifies which server to use. Currently, **minet-core** has three server implementation.\n\n- `Basic`: Default option, a blocking server that handles requests synchronously.\n- `Threaded`: A server that handles requests in multiple threads with a thread pool.\n- `Mayhem`: An experimental server that handles requests using both epoll and thread pool.\n\nIf you choose to use `Basic` server, then `threads` and `capacity` are ignored. For `Threaded` and `Mayhem` server, `threads` is the number of worker threads, and `capacity` is the maximum requests queued on each worker thread.\n\n### Logging\n\n**minet-core** uses`spdlog` for logging, and you can configure it in the `logging` section. The format of logging settings is as follows.\n\n```json\n{\n    \"logging\": {\n        \"level\": \"Debug\",\n        \"pattern\": \"\",\n        \"sinks\": [\n            {\n                \"file\": \"stdout\"\n            },\n            {\n                \"pattern\": \"[%Y-%m-%d %H:%M:%S] %8l [%6n]: %v\",\n                \"file\": \"server.log\"\n            }\n        ],\n        \"loggers\": {\n            \"Demo\": {\n                \"level\": \"Debug\",\n                \"pattern\": \"%^[%Y-%m-%d %H:%M:%S] %l [%6n]: %v%$\",\n                \"sinks\": [\n                    {\n                        \"file\": \"stdout\"\n                    },\n                    {\n                        \"file\": \"demo.log\"\n                    }\n                ]\n            }\n        }\n    }\n}\n```\n\nIn the top level of `logging` are default configurations. And specific configurations for individual loggers are under `loggers`. Each logger has its own `level`, `pattern`, and `sinks`. If one of these are missing, it will inherit from the default settings.\n\n`level` is the logging level, and it can be one of the following: `All`, `Fine`, `Debug`, `Info`, `Warning`, `Error`, `Critical`, `Disabled`.\n\n`pattern` is the format of log messages. See [spdlog/Custom formatting](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting#customizing-format-using-set_pattern) for more information. By default, it is empty, using the default pattern of `spdlog`. If it is missing, will inherit from the default one.\n\n`sinks` is the output destination of the log. For `file` field, you can use `stdout` or `stderr` for console output, or specify a file path for file output. You can also specify `pattern` here. If pattern is missing, it will use the `pattern` in the current logger.\n\n### Custom Settings\n\nOf course, you can add other settings in the configuration file. In this case, you have to manually handle them in your code. To get the original configuration JSON, use `WebHostBuilder::GetAppSettings()`.\n\n## Dependency Injection\n\n\u003e [!NOTE]\n\u003e **minet-core** uses [MinIoC](https://github.com/Lord-Turmoil/MinIoC) as the IoC container for dependency injection. See that repository for more information on how to use the container.\n\nBehind the settings, **minet-core** uses dependency injection to manage all the pluggable components. You can get the IoC container via `WebHost::GetServiceContainer()`. It uses lazy initialization for singletons. Also, configurations are also injected into the container, you can get them by resolving `ServerConfig` and `LoggerConfig`.\n\nIf you want to add custom components, or replace the built-in ones, you can then register whatever you want after `UseAppSettings()`. The existing components will be replaced if you register the same interface again.\n\n---\n\n# Considerations\n\n\u003e [!NOTE]\n\u003eThis section contains some personal design preferences.\n\n## Heap vs Stack\n\nYou may notice that, in **minet-core**, some classes have private constructors, so that one can only create them in heap using the provided factory function. Why? Because I personally prefer using `-\u003e` in chained calls, and I don't want to mix `.` and `-\u003e` up. It eliminates the use of raw pointers, but also robs the freedom of choosing stack or heap.\n\n---\n\n# Acknowledgement\n\n**minet-core** uses some open source libraries, thanks to their great work!🥰\n\n- [nlohmann/json](https://github.com/nlohmann/json) v3.11.3\n- [gabime/spdlog](https://github.com/gabime/spdlog) v1.15.0\n- [Lord-Turmoil/MinIoC](https://github.com/Lord-Turmoil/MinIoC) v1.3.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flord-turmoil%2Fminet-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flord-turmoil%2Fminet-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flord-turmoil%2Fminet-core/lists"}