{"id":49017974,"url":"https://github.com/jchristn/HttpServerLite","last_synced_at":"2026-05-05T06:01:30.170Z","repository":{"id":39163047,"uuid":"275220135","full_name":"jchristn/HttpServerLite","owner":"jchristn","description":"TCP-based user-space HTTP and HTTPS server, written in C#, with no dependency on http.sys.","archived":true,"fork":false,"pushed_at":"2023-11-02T17:56:24.000Z","size":7083,"stargazers_count":76,"open_issues_count":4,"forks_count":21,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-11-27T13:00:16.594Z","etag":null,"topics":["http","http-server","rest","rest-api","restful","restful-api","web","webserver"],"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/jchristn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":["jchristn"],"custom":["https://paypal.me/joelchristner"]}},"created_at":"2020-06-26T18:16:31.000Z","updated_at":"2025-10-15T04:34:40.000Z","dependencies_parsed_at":"2023-02-15T13:15:29.979Z","dependency_job_id":"1a1b138a-262f-4195-ba07-0d791e3a7bab","html_url":"https://github.com/jchristn/HttpServerLite","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jchristn/HttpServerLite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristn%2FHttpServerLite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristn%2FHttpServerLite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristn%2FHttpServerLite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristn%2FHttpServerLite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jchristn","download_url":"https://codeload.github.com/jchristn/HttpServerLite/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jchristn%2FHttpServerLite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32637556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"online","status_checked_at":"2026-05-05T02:00:06.033Z","response_time":54,"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":["http","http-server","rest","rest-api","restful","restful-api","web","webserver"],"created_at":"2026-04-19T03:00:28.351Z","updated_at":"2026-05-05T06:01:30.136Z","avatar_url":"https://github.com/jchristn.png","language":"C#","funding_links":["https://github.com/sponsors/jchristn","https://paypal.me/joelchristner"],"categories":["C# #"],"sub_categories":[],"readme":"# OBSOLETE\n\nHttpServerLite has been merged with the .NET Foundation project [WatsonWebserver](https://github.com/dotnet/WatsonWebserver) as a subproject called ```Watson.Lite```.  \n\nThis repository has been moved to public archive as a result.  \n\nWe are thankful to the community that has contributed to this work and welcome you to continue efforts on the new repository!\n\n\n\n\n![alt tag](https://raw.githubusercontent.com/jchristn/HttpServerLite/master/Assets/icon.ico)\n\n# HttpServerLite\n\n[![NuGet Version](https://img.shields.io/nuget/v/HttpServerLite.svg?style=flat)](https://www.nuget.org/packages/HttpServerLite/) [![NuGet](https://img.shields.io/nuget/dt/HttpServerLite.svg)](https://www.nuget.org/packages/HttpServerLite) \n\nTCP-based user-space HTTP and HTTPS server, written in C#, with no dependency on http.sys.\n\n## New in v2.1.x\n\n- ```HostBuilder``` feature to quickly build servers, thank you @sapurtcomputer30!\n- Bugfix for ```HttpContext.HttpRequest.Data``` not ending, thank you @ChZhongPengCheng33\n\n## Special Thanks\n\nI'd like to extend a special thanks to those that have provided motivation or otherwise directly helped make HttpServerLite better.\n\n- @winkmichael @Job79 @MartyIX @sqlnew @SaintedPsycho @Return25 @marcussacana @samisil \n- @Jump-Suit @sapurtcomputer30 @ChZhongPengCheng33 @bobaoapae\n\n## Performance\n\nHttpServerLite is quite fast, however, it's in user-space and may be slower than other webservers that have the benefit of a kernel-mode driver (such as ```http.sys``` and IIS or Watson). \n\n## Getting Started\n\nRefer to the ```Test``` project for a working example.\n\nIt is important to under that that HttpServerLite is minimalistic and leaves control to you on which headers are set.  Thus it is important to understand the following:\n\n- ```server.Settings.Headers``` contains default values for a series of HTTP headers\n  - These will be included **in every response** if they have a value assigned\n  - The values in ```server.Settings.Headers``` can be written directly, or\n    - You can modify per-response values by using ```ctx.Response.Headers.Add(\"[header]\", \"[value]\")```\n    - Values set in ```ctx.Response.Headers``` will override any value in ```server.Settings.Headers``` for that response only\n  - The headers automatically set if a value is supplied include\n    - Access-Control-Allow-[Origin|Methods|Headers]\n    - Access-Control-Expose-Headers\n    - Accept\n    - Accept-[Language|Charset]\n    - Connection\n    - Host\n  - ```Connection``` is an example of one of these headers.  By default it is set to ```close```, therefore you should:\n    - Leave it as is\n    - Explicitly set it prior to sending a response using ```ctx.Response.Headers.Add(\"connection\", \"value\")```, or\n    - Set the default value in ```server.Settings.Headers.Connection```\n- ```ctx.Response.ContentLength``` should be set if you want the ```Content-Length``` header to be sent\n- ```server.Settings.Headers.Host``` should be set when instantiating the server though it is not required\n\n### Simple Server\n```csharp\nusing System;\nusing System.Threading.Tasks;\nusing HttpServerLite;\n\nnamespace Test\n{\n  class Program\n  {\n    static Webserver _Server;\n\n    static void Main(string[] args)\n    {\n      Webserver server = new Webserver(\"localhost\", 9000, false, null, null, DefaultRoute); \n      server.Settings.Headers.Host = \"https://localhost:9000\";\n      server.Start();\n      Console.WriteLine(\"HttpServerLite listening on http://localhost:9000\");\n      Console.WriteLine(\"ENTER to exit\");\n      Console.ReadLine();\n    }\n         \n    static async Task DefaultRoute(HttpContext ctx)\n    {\n      string resp = \"Hello from HttpServerLite!\";\n      ctx.Response.StatusCode = 200; \n      ctx.Response.ContentLength = resp.Length;\n      ctx.Response.ContentType = \"text/plain\";\n      await ctx.Response.SendAsync(resp);\n    }\n  }\n} \n```\n\n## Routing\n\nHttpServerLite includes the following routing capabilities.  These are listed in the other in which they are processed within HttpServerLite:\n\n- ```server.Settings.AccessControl``` - access control based on IP address\n  - You can specify the ```Mode``` to either be ```DefaultPermit``` or ```DefaultDeny```\n    - ```DefaultPermit``` will allow everything unless explicitly blocked through ```DenyList```\n    - ```DefaultDeny``` will deny everything unless explicitly permitted through ```PermitList```\n    - The default value is ```DefaultPermit```\n- ```server.Routes.Preflight``` - a default route to use when the HTTP verb is ```OPTIONS```\n  - When set, the connection is terminated after being handled by ```server.OptionsRoute```\n- ```server.Routes.PreRouting``` - a route through which **all** requests will pass, useful for authentication, logging, and other functions\n  - If defined, return ```true``` from this task if you wish to terminate the connection\n  - Otherwise return ```false``` to allow routing to continue\n- ```server.Routes.Content``` - serve GET and HEAD requests for static content based on URL path\n  - Content will be read from the ```server.Routes.Content.BaseDirectory``` plus the URL path\n  - An entire directory can be listed as a content route when adding the route\n- ```server.Routes.Static``` - invoke functions based on specific HTTP method and URL combinations\n- ```server.Routes.Parameter``` - invoke functions based on specific HTTP method and URLs with embedded parameters.  These values are returned in ```HttpContext.HttpRequest.Url.Parameters```\n- ```server.Routes.Dynamic``` - invoke functions based on specific HTTP method and a regular expression for the URL\n- ```server.Routes.Default``` - any request that did not match a content route, static route, or dynamic route, is routed here\n\nAdditionally, you can annotate your own methods using the ```StaticRoute```, ```ParameterRoute```, or ```DynamicRoute``` attributes.  Methods decorated with these attributes must be marked as ```public```.\n\n```csharp\nWebserver server = new Webserver(\"localhost\", 9000, false, null, null, DefaultRoute);\nserver.Start();\n\n[StaticRoute(HttpMethod.GET, \"/static\")]\npublic static async Task MyStaticRoute(HttpContext ctx)\n{\n  string resp = \"Hello from the static route\";\n  ctx.Response.StatusCode = 200;\n  ctx.Response.ContentType = \"text/plain\";\n  ctx.Response.ContentLength = resp.Length;\n  await ctx.Response.SendAsync(resp);\n  return;\n}\n\n[ParameterRoute(HttpMethod.GET, \"/{version}/api/{id}\")]\npublic static async Task MyParameterRoute(HttpContext ctx)\n{\n  string resp = \"Hello from parameter route version \" + ctx.Request.Url.Parameters[\"version\"] + \" for ID \" + ctx.Request.Url.Parameters[\"id\"];\n  ctx.Response.StatusCode = 200;\n  ctx.Response.ContentType = \"text/plain\";\n  ctx.Response.ContentLength = resp.Length;\n  await ctx.Response.SendAsync(resp);\n  return;\n}\n\n[DynamicRoute(HttpMethod.GET, \"^/dynamic/\\\\d+$\")]\npublic static async Task MyDynamicRoute(HttpContext ctx)\n{\n  string resp = \"Hello from the dynamic route\";\n  ctx.Response.StatusCode = 200;\n  ctx.Response.ContentType = \"text/plain\";\n  ctx.Response.ContentLength = resp.Length;\n  await ctx.Response.SendAsync(resp);\n  return;\n}\n```\n\n## Authorizing or Declining a Connection\n```\nserver.Callbacks.AuthorizeConnection = AuthorizeConnection;\n\nprivate static bool AuthorizeConnection(string ipAddress, int port)\n{\n  // evaluate the IP address and port\n  return true;  // permit\n  return false; // deny\n}\n```\n\n## HostBuilder\n\n```HostBuilder``` helps you set up your server much more easily by introducing a chain of settings and routes instead of using the server class directly.\n\n```csharp\nusing WatsonWebserver.Extensions.HostBuilderExtension;\n\nServer server = new HostBuilder(\"127.0.0.1\", 8000, false, DefaultRoute)\n                .MapStaticRoute(WatsonWebserver.HttpMethod.GET, GetUrlsRoute, \"/links\")\n                .MapStaticRoute(WatsonWebserver.HttpMethod.POST, CheckLoginRoute, \"/login\")\n                .MapStaticRoute(WatsonWebserver.HttpMethod.POST, TestRoute, \"/test\")\n                .Build();\n\nserver.Start();\n\nConsole.WriteLine(\"Server started\");\nConsole.ReadKey();\n\nstatic async Task DefaultRoute(HttpContext ctx) =\u003e \n    await ctx.Response.SendAsync(\"Hello from default route!\"); \n\nstatic async Task GetUrlsRoute(HttpContext ctx) =\u003e \n    await ctx.Response.SendAsync(\"Here are your links!\"); \n\nstatic async Task CheckLoginRoute(HttpContext ctx) =\u003e \n    await ctx.Response.SendAsync(\"Checking your login!\"); \n\nstatic async Task TestRoute(HttpContext ctx) =\u003e \n    await ctx.Response.SendAsync(\"Hello from the test route!\"); \n```\n\n## Accessing from Outside Localhost\n\nWhen you configure HttpServerLite to listen on ```127.0.0.1``` or ```localhost```, it will only respond to requests received from within the local machine.\n\nTo configure access from other nodes outside of ```localhost```, use the following:\n\n- Specify the IP address on which HttpServerLite should listen in the Server constructor. \n- If you want to listen on more than one IP address, use ```*``` or ```+```\n- If you listen on anything other than ```localhost``` or ```127.0.0.1```, you may have to run HttpServerLite as administrator (operating system dependent)\n- If you want to use a port number less than 1024, you MUST run HttpServerLite as administrator (this is an operating system limitation)\n- Open a port on your firewall to permit traffic on the TCP port upon which HttpServerLite is listening\n- If you're still having problems, please do not hesitate to file an issue here, and I will do my best to help and update the documentation\n\n## Version History\n\nRefer to CHANGELOG.md for version history.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristn%2FHttpServerLite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjchristn%2FHttpServerLite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjchristn%2FHttpServerLite/lists"}