{"id":50257015,"url":"https://github.com/lorenzoconcas/hsb","last_synced_at":"2026-05-27T07:00:52.805Z","repository":{"id":177562344,"uuid":"634760529","full_name":"lorenzoconcas/HSB","owner":"lorenzoconcas","description":"Http Server Boxed it's a little library that provides and entire webserver in C#","archived":false,"fork":false,"pushed_at":"2026-05-26T20:58:58.000Z","size":38103,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-26T21:17:03.786Z","etag":null,"topics":["csh","http-server","httpserver"],"latest_commit_sha":null,"homepage":"https://lorenzoconcas.github.io/HSB/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lorenzoconcas.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2023-05-01T05:39:33.000Z","updated_at":"2026-05-26T20:59:03.000Z","dependencies_parsed_at":"2023-10-14T03:03:02.883Z","dependency_job_id":"7f8e352e-f151-4e7a-8bad-fcf468bae14a","html_url":"https://github.com/lorenzoconcas/HSB","commit_stats":null,"previous_names":["lorenzoconcas/hsb-sharp","lorenzoconcas/hsb"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/lorenzoconcas/HSB","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzoconcas%2FHSB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzoconcas%2FHSB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzoconcas%2FHSB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzoconcas%2FHSB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lorenzoconcas","download_url":"https://codeload.github.com/lorenzoconcas/HSB/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lorenzoconcas%2FHSB/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33554780,"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-05-27T02:00:06.184Z","response_time":53,"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":["csh","http-server","httpserver"],"created_at":"2026-05-27T07:00:50.848Z","updated_at":"2026-05-27T07:00:52.800Z","avatar_url":"https://github.com/lorenzoconcas.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HSB\n\n![HSB banner](banner.png)\n\n[![.NET](https://img.shields.io/badge/.NET-net10.0-512BD4)](https://dotnet.microsoft.com/)\n[![Version](https://img.shields.io/badge/version-0.0.18-blue)](./VERSIONS.md)\n[![License](https://img.shields.io/badge/license-see%20LICENSE.md-lightgrey)](./LICENSE.md)\n\n\nHSB, historically short for HttpServerBoxed, is an HTTP and WebSocket web/server framework written in C#. It started as a study project focused on understanding how a web server works, but the current architecture has evolved into a lightweight framework for HTTP APIs, WebSocket communication, streaming, and embedded servers.\n\nThe project is still pre-1.0: APIs may change between releases and even between individual commits. For stable projects, it is recommended to use the published artifacts in Releases/ and read VERSIONS.md￼ before upgrading.\n\nIntroduction\n\nHSB currently provides:\n\nArea\tCurrent support\nHTTP server\tTCP sockets, routing, static files, embedded resources\nModern routing\tAttribute-based controllers and minimal API/Express-style mappings\nControllers\t[Controller], [Get], [Post], [Route], route parameters, Request and Response injection\nWebSocket\tModern endpoints via Configuration.WebSocket(...) and [Ws] inside controllers\nStreaming\tChunked responses with InitStream, AddStreamChunk, EndStream\nSecurity\tHeader/request limits, timeouts, anti-Slowloris hardening, CORS, IP filters, TLS\nMiddleware/hooks\tGlobal modules, request interceptors, request handler interceptors, service modules\nTLS\tSslConfiguration, .p12/.pkcs12 certificates, native .NET TLS and experimental HSB handler\nOpenAPI\tAttributes and dedicated handlers for API documentation\n\nPhilosophy\n\nHSB aims to stay small, explicit, and close to the protocol. The framework does not hide the HTTP lifecycle: it exposes Request, Response, sockets, headers, cookies, sessions, TLS, and WebSocket directly.\n\nThe modern design focuses on three ways of building applications:\n\n* Attribute-based controllers for APIs organized by functional area.\n* Minimal API style with config.Get(...), config.Post(...), config.WebSocket(...) for small endpoints or prototypes.\n* Modules for cross-cutting hooks such as authentication, filtering, and pre/post-routing logic.\n\nThe old Servlet and [Binding] model has been removed: routes are now defined through controllers or direct mappings on Configuration.\n\nInstallation\n\nClone the repository and build the solution:\n\ngit clone https://github.com/lorenzoconcas/HSB.git\ncd HSB\ndotnet build HSB.sln\n\nThe core project is HSB/HSB.csproj and currently targets net10.0.\n\nTo get started quickly you can use:\n\n* Examples/HelloWorld\n* Examples/ControllerExample\n* Examples/StreamingResponse\n* Experiments/StressTest\n* Runner to test many features together\n\nQuick Start\n\nMinimal example using Express/minimal API-style mappings:\n\nusing HSB;\nConfiguration config = new()\n{\nPort = 8080\n};\nconfig.Get(\"/\", (Request req, Response res) =\u003e\n{\nres.Send(\"Hello from HSB\");\n});\nconfig.Get(\"/json\", (Request req, Response res) =\u003e\n{\nres.Json(new\n{\nmessage = \"ok\",\ntimestamp = DateTime.UtcNow\n});\n});\nnew Server(config).Start();\n\nRun:\n\ndotnet run --project Examples/HelloWorld/HelloWorld.csproj\n\nRouting\n\nHSB registers routes from two sources:\n\n1. Direct mappings on Configuration, such as config.Get(...).\n2. Controllers marked with [Controller].\n\nThe actual resolution order inside the server is:\n\nExpress/minimal mapping -\u003e Controller -\u003e static files/embedded resources -\u003e 404\n\nMinimal API style\n\nconfig.Get(\"/health\", (Request req, Response res) =\u003e\n{\nres.Json(new\n{\nstatus = \"ok\",\nuptime = Environment.TickCount64\n});\n});\nconfig.Post(\"/auth/login\", (Request req, Response res) =\u003e\n{\nif (!req.Body.Contains(\"admin\"))\n{\nres.Json(new { error = \"invalid_credentials\" }, 401);\nreturn;\n}\nres.Json(new\n{\naccessToken = Guid.NewGuid(),\nexpiresIn = 3600\n});\n});\n\nHelpers are available for Get, Post, Put, Delete, Patch, Head, Options, Trace, and Connect.\n\nRoute parameters\n\nInside controllers you can use :name route segments. Values are copied into req.Parameters.\n\n[Controller(\"/users\")]\npublic class UserController\n{\n[Get(\"/:id\")]\nprivate void GetById(Request req, Response res)\n{\nres.Json(new\n{\nid = req.Parameters[\"id\"]\n});\n}\n}\n\nYou can also request typed parameters through [NamedParameter]:\n\nusing HSB.Components.Attributes;\nusing HSB.Components.Controller;\n[Controller(\"/users\")]\npublic class UserController\n{\nprivate Response res = null!;\n[Get(\"/:id\")]\nprivate void GetById([NamedParameter(\"id\", true)] int id)\n{\nres.Json(new { id });\n}\n}\n\nControllers\n\nThe new controller system is the recommended way to build HSB applications. A controller is a normal C# class marked with [Controller(\"/base-path\")]; it does not need to inherit from Servlet.\n\nusing HSB;\nusing HSB.Components.Controller;\n[Controller(\"/api\")]\npublic class UserController\n{\n[Get(\"/users\")]\npublic void GetUsers(Request req, Response res)\n{\nres.Send(\"ok\");\n}\n[Post(\"/users\")]\nprivate void CreateUser(Request req, Response res)\n{\nres.Json(new\n{\ncreated = true,\nbody = req.Body\n});\n}\n}\n\nAvailable attributes\n\nAttribute\tUsage\n[Controller(\"/path\")]\tDeclares the controller prefix\n[Get(\"/path\")]\tHTTP GET route\n[Post(\"/path\")]\tHTTP POST route\n[Put(\"/path\")]\tHTTP PUT route\n[Delete(\"/path\")]\tHTTP DELETE route\n[Patch(\"/path\")]\tHTTP PATCH route\n[Head(\"/path\")]\tHTTP HEAD route\n[Options(\"/path\")]\tHTTP OPTIONS route\n[Route(\"/path\", HttpMethod.X)]\tRoute with explicit method\n[Ws(\"/path\")]\tWebSocket endpoint inside the controller\n\nRequest and Response injection\n\nHSB can inject Request and Response:\n\n* as method parameters;\n* as public, private, or protected controller fields;\n* through fields when the method uses parameters annotated with [NamedParameter].\n\n[Controller(\"/reports\")]\npublic class ReportController\n{\nprivate Response res = null!;\n[Get(\"/:year\")]\nprivate void GetReport([NamedParameter(\"year\", true)] int year)\n{\nres.Json(new { year });\n}\n}\n\nDifferences compared to Servlet\n\nLegacy Servlet\tModern Controller\nInherits from Servlet\tPlain C# class\nRoutes via [Binding]\tRoutes via [Controller] and HTTP attributes\nOverride GET(), POST(), etc.\tFree methods marked with [Get], [Post], etc.\nOne handler per class/route\tMultiple routes per controller\nLegacy servlet-style WebSocket\t[Ws] or config.WebSocket(...)\n\nWebSocket\n\nThe modern WebSocket model uses WebSocketConnection. Each connection exposes lifecycle hooks, text/binary sending, state, request context, and endpoint-level broadcasting.\n\nController style\n\nusing HSB;\nusing HSB.Components.Controller;\nusing HSB.Components.WebSockets;\n[Controller(\"/realtime\")]\npublic class ChatController\n{\n[Ws(\"/chat\")]\npublic void Chat(WebSocketConnection socket)\n{\nsocket.OnOpen(() =\u003e\n{\nsocket.Send(\"connected\");\n});\nsocket.OnMessage(msg =\u003e\n{\nsocket.Send(msg.Text);\n});\nsocket.OnClose(() =\u003e\n{\nTerminal.Info(\"WebSocket closed\");\n});\n}\n}\n\nThe final route in this example is /realtime/chat.\n\nMinimal API style\n\nconfig.WebSocket(\"/ws\", socket =\u003e\n{\nsocket.OnMessage(msg =\u003e\n{\nsocket.Send(msg.Text);\n});\n});\n\nAsync support\n\nconfig.WebSocket(\"/events\", async socket =\u003e\n{\nawait Task.Yield();\nsocket.OnOpen(async () =\u003e\n{\nawait socket.SendAsync(\"connected\");\n});\nsocket.OnMessage(async msg =\u003e\n{\nawait socket.SendAsync(\"received:\" + msg.Text);\n});\n});\n\nLifecycle\n\nHook\tWhen it runs\nOnOpen\tAfter the HTTP 101 handshake and connection opening\nOnMessage\tFor every received text/binary frame\nOnClose\tWhen the connection closes\nOnError\tWhen the runtime intercepts a connection error\n\nBroadcast\n\nconfig.WebSocket(\"/chat\", socket =\u003e\n{\nsocket.OnMessage(msg =\u003e\n{\nsocket.BroadcastExceptSelf(msg.Text);\n});\n});\n\nBroadcast(...) sends to every connection on the same route; BroadcastExceptSelf(...) excludes the current connection.\n\nStreaming\n\nHSB supports chunked HTTP responses through Response.\n\nusing System.Text.Json;\nconfig.Get(\"/stream\", async (Request req, Response res) =\u003e\n{\nawait res.InitStream(\"application/x-ndjson\");\nfor (int i = 0; i \u003c 10; i++)\n{\nstring payload = JsonSerializer.Serialize(new\n{\ntype = \"event\",\nindex = i,\ntimestamp = DateTime.UtcNow\n});\nawait res.AddStreamChunk(payload + \"\\n\");\nawait Task.Delay(250);\n}\nawait res.AddStreamChunk(JsonSerializer.Serialize(new { type = \"done\" }) + \"\\n\");\nawait res.EndStream();\n});\n\napplication/x-ndjson is useful when you want to send one JSON object per line without waiting for the entire processing to finish. The client can progressively read each chunk and update UI, logs, or dashboards in real time.\n\nUse streaming for:\n\n* lightweight server-side events;\n* real-time logs;\n* progressive exports;\n* long-running jobs with incremental state;\n* integrations consuming NDJSON.\n\nRequest/Response lifecycle\n\nThe HTTP request lifecycle is:\n\n1. Server accepts the TCP connection and sets timeouts.\n2. Headers are read until \\r\\n\\r\\n, respecting size and count limits.\n3. Request parses the request line, query string, headers, cookies, auth, session, body, and uploads.\n4. RequestInterceptor modules can accept or reject the request.\n5. The HTTP or WebSocket route is resolved.\n6. RequestHandlerInterceptor modules can intervene before the handler.\n7. The handler writes to Response.\n8. The connection is closed or kept alive by the runtime when needed, such as for WebSocket or streaming.\n\nResponse includes helpers for:\n\n* Send(...) for text or bytes;\n* Json(...) and SendJson(...);\n* SendFile(...);\n* SendHtmlFile(...) and SendHtmlContent(...);\n* Redirect(...);\n* SendCode(...);\n* InitStream(...), AddStreamChunk(...), EndStream(...).\n\nMiddleware and modules\n\nHSB uses a module system annotated with [Module] and [ModuleInvokeMethod]. Modules can act as:\n\nModule type\tTypical usage\nGlobal\tGlobal setup\nService\tServices started with the server\nRequestInterceptor\tFilters before route resolution\nRequestHandlerInterceptor\tHooks before the resolved handler\n\nExamples inside the project:\n\n* HSB/Modules/Filter.cs for IP allowlist/banlist.\n* HSB/Modules/Authentication.cs for [RequireAuth], Bearer, Basic, API keys, and custom validation.\n* HSB/Modules/OpenApi.cs for documentation integration.\n\nAuthentication example:\n\nusing HSB.Modules;\nAuthenticationSettings.Instance.EnableBearer = true;\nAuthenticationManager.Instance.AddBearerToken(\"dev-token\");\n[Controller(\"/admin\")]\npublic class AdminController\n{\n[Get(\"/stats\")]\n[RequireAuth(AuthType.Bearer)]\nprivate void Stats(Response res)\n{\nres.Json(new { status = \"protected\" });\n}\n}\n\nSSL/TLS\n\nTLS configuration goes through SslConfiguration.\n\nusing HSB;\nusing HSB.Constants.TLS;\nSslConfiguration ssl = new(\"certificate.p12\", \"password\")\n{\nPortMode = SSL_PORT_MODE.DUAL_PORT,\nSslPort = 8443,\nUpgradeUnsecureRequests = true,\nSslHandler = SslHandler.Native\n};\nConfiguration config = new()\n{\nPort = 8080,\nSslSettings = ssl\n};\nnew Server(config).Start();\n\nFeatures:\n\n* .p12 or .pkcs12 certificates;\n* dual-port HTTP/HTTPS or single-port mode;\n* automatic redirect of insecure requests when UpgradeUnsecureRequests is enabled;\n* native .NET TLS as the recommended path;\n* experimental HSB TLS handler for development and research;\n* TLS 1.0 and TLS 1.1 are deprecated: using obsolete versions throws exceptions.\n\nFor local development you can use UseDebugCertificate, which creates/loads a temporary certificate if OpenSSL is available.\n\nPerformance\n\nHSB includes a stress test project in Experiments/StressTest with realistic endpoints: healthcheck, fake login, medium JSON, large payload, slow endpoint, NDJSON streaming, and WebSocket broadcast.\n\nObserved results from recent project tests:\n\nScenario\tApproximate result\nMinimal endpoint\taround 18k req/s\nMedium JSON\taround 8k req/s\nConcurrency stress\tstable in recent tests\nSlowloris resilience\tslow connections closed through timeouts/limits\nConnection storm\timproved stability with timeouts and concurrent handling\n\nThese numbers are indicative and depend on machine, .NET runtime, operating system, socket configuration, payload, logging, and benchmarking tools. They are not a production throughput guarantee.\n\nHardening and security\n\nRecent refactors mainly strengthened the networking and parsing pipeline:\n\n* socket receive/send timeouts;\n* closing connections that do not complete headers in time;\n* header size limits;\n* request line length limits;\n* maximum header count;\n* more defensive parsing of request lines, query strings, headers, cookies, auth, and bodies;\n* case-insensitive dictionaries for headers, parameters, and cookies;\n* snapshots of global headers/cookies while building responses;\n* locks/semaphores in WebSocket connections for handlers and frame sending;\n* concurrent WebSocket connection management through ConcurrentDictionary;\n* global and per-response CORS support;\n* IP allowlist/banlist through the Filter module;\n* optional HTTPS redirect.\n\nAnti-Slowloris protection is based on timeouts, header limits, and requiring header completion before parsing.\n\nReal-world examples\n\nJSON API\n\n[Controller(\"/api\")]\npublic class ApiController\n{\n[Get(\"/status\")]\nprivate void Status(Response res)\n{\nres.Json(new\n{\nstatus = \"ok\",\nversion = typeof(Server).Assembly.GetName().Version?.ToString()\n});\n}\n}\n\nUpload/form data\n\nRequest exposes body, parameters, cookies, authentication, and form/upload helpers. See Examples/FormHandling and Runner/Servlets/FileUpload.cs for complete examples.\n\nStatic files\n\nConfiguration config = new()\n{\nPort = 8080,\nStaticFolderPath = \"./www\"\n};\n\nIf a route is not resolved through mappings/controllers/servlets, HSB tries to serve static files from the configured folder.\n\nWebSocket chat\n\nconfig.WebSocket(\"/chat\", socket =\u003e\n{\nsocket.OnOpen(() =\u003e socket.Broadcast(\"new client connected\"));\nsocket.OnMessage(msg =\u003e socket.BroadcastExceptSelf(msg.Text));\nsocket.OnClose(() =\u003e socket.Broadcast(\"client disconnected\"));\n});\n\nProject structure\n\nPath\tDescription\nHSB/\tCore library: server, request/response, routing, controllers, WebSocket, TLS, modules\nRunner/\tDevelopment application used to test HSB in action\nExamples/\tSmall examples focused on specific APIs\nExperiments/\tPrototypes and stress tests for advanced features\nDocumentation/\tManual/authored project documentation\ndocs/\tDoxygen-generated output, not intended as the primary documentation source\nLauncher/\tTool for launching HSB projects through a dedicated entry point\nBootstrapper/\tUtilities/templates to make HSB directly executable\nTemplate/\tVisual Studio template\nTests/\tTests and experimental assets\nReleases/\tArchive of previous releases\n\nRemoved APIs\n\nServlet\n\nServlet, [Binding], and servlet-style routing have been removed. Use controllers or direct mappings instead.\n\nModern equivalent using controllers:\n\n[Controller(\"/legacy\")]\npublic class ExampleController\n{\n[Get(\"/\")]\nprivate void Get(Response res)\n{\nres.Send(\"ok\");\n}\n}\n\nServlet-style WebSocket\n\nThe old inheritable/class-based WebSocket approach using [Binding] has been removed. Use:\n\n* config.WebSocket(\"/path\", socket =\u003e { ... });\n* [Ws(\"/path\")] inside a controller.\n\nServlet -\u003e Controller migration\n\n1. Replace [Binding(\"/path\")] with [Controller(\"/path\")].\n2. Remove inheritance from Servlet.\n3. Transform GET(), POST(), etc. into methods annotated with [Get], [Post], etc.\n4. Receive Request and Response as parameters or fields.\n5. Group related routes inside the same controller when they belong to the same functional area.\n6. Replace legacy WebSocket with [Ws] or config.WebSocket.\n\nWhy use HSB\n\nHSB is suitable when you want:\n\n* an embedded and controllable C# server;\n* lightweight APIs without a full web stack;\n* to experiment with low-level HTTP, sockets, TLS, or WebSocket;\n* fast prototypes with modern routing;\n* NDJSON streaming or WebSocket without heavy dependencies;\n* an educational but now structured framework.\n\nFor enterprise services with a complete ecosystem, managed hosting, standardized middleware, and long-term support, ASP.NET Core remains the primary choice.\n\nRoadmap\n\nRecommended priorities for the next iterations:\n\n* fully stabilize the controller system;\n* consolidate modern WebSocket and broadcasting support;\n* make benchmarks reproducible with scripts and documented environments;\n* strengthen automated tests for parsing, timeouts, streaming, and WebSocket;\n* improve OpenAPI documentation;\n* clarify compatibility and target framework support for each release;\n* reach a stable API surface ahead of a future 1.0 release.\n\nResources\n\n* Project Webpage￼\n* Versions and migrations￼\n* WebSocket Documentation￼\n* SSL Documentation￼\n* Response Documentation￼","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzoconcas%2Fhsb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Florenzoconcas%2Fhsb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Florenzoconcas%2Fhsb/lists"}