HttpServerLite 2.1.0
See the version list below for details.
dotnet add package HttpServerLite --version 2.1.0
NuGet\Install-Package HttpServerLite -Version 2.1.0
<PackageReference Include="HttpServerLite" Version="2.1.0" />
paket add HttpServerLite --version 2.1.0
#r "nuget: HttpServerLite, 2.1.0"
// Install HttpServerLite as a Cake Addin #addin nuget:?package=HttpServerLite&version=2.1.0 // Install HttpServerLite as a Cake Tool #tool nuget:?package=HttpServerLite&version=2.1.0
HttpServerLite
TCP-based user-space HTTP and HTTPS server, written in C#, with no dependency on http.sys.
New in v2.1.x
HostBuilder
feature to quickly build servers, thank you @sapurtcomputer30!
Special Thanks
I'd like to extend a special thanks to those that have provided motivation or otherwise directly helped make HttpServerLite better.
- @winkmichael @Job79 @MartyIX @sqlnew @SaintedPsycho @Return25 @marcussacana @samisil
- @Jump-Suit @sapurtcomputer30
Performance
HttpServerLite 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).
Getting Started
Refer to the Test
project for a working example.
It 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:
server.Settings.Headers
contains default values for a series of HTTP headers- These will be included in every response if they have a value assigned
- The values in
server.Settings.Headers
can be written directly, or- You can modify per-response values by using
ctx.Response.Headers.Add("[header]", "[value]")
- Values set in
ctx.Response.Headers
will override any value inserver.Settings.Headers
for that response only
- You can modify per-response values by using
- The headers automatically set if a value is supplied include
- Access-Control-Allow-[Origin|Methods|Headers]
- Access-Control-Expose-Headers
- Accept
- Accept-[Language|Charset]
- Connection
- Host
Connection
is an example of one of these headers. By default it is set toclose
, therefore you should:- Leave it as is
- Explicitly set it prior to sending a response using
ctx.Response.Headers.Add("connection", "value")
, or - Set the default value in
server.Settings.Headers.Connection
ctx.Response.ContentLength
should be set if you want theContent-Length
header to be sentserver.Settings.Headers.Host
should be set when instantiating the server though it is not required
Simple Server
using System;
using System.Threading.Tasks;
using HttpServerLite;
namespace Test
{
class Program
{
static Webserver _Server;
static void Main(string[] args)
{
Webserver server = new Webserver("localhost", 9000, false, null, null, DefaultRoute);
server.Settings.Headers.Host = "https://localhost:9000";
server.Start();
Console.WriteLine("HttpServerLite listening on http://localhost:9000");
Console.WriteLine("ENTER to exit");
Console.ReadLine();
}
static async Task DefaultRoute(HttpContext ctx)
{
string resp = "Hello from HttpServerLite!";
ctx.Response.StatusCode = 200;
ctx.Response.ContentLength = resp.Length;
ctx.Response.ContentType = "text/plain";
await ctx.Response.SendAsync(resp);
}
}
}
Routing
HttpServerLite includes the following routing capabilities. These are listed in the other in which they are processed within HttpServerLite:
server.Settings.AccessControl
- access control based on IP address- You can specify the
Mode
to either beDefaultPermit
orDefaultDeny
DefaultPermit
will allow everything unless explicitly blocked throughDenyList
DefaultDeny
will deny everything unless explicitly permitted throughPermitList
- The default value is
DefaultPermit
- You can specify the
server.Routes.Preflight
- a default route to use when the HTTP verb isOPTIONS
- When set, the connection is terminated after being handled by
server.OptionsRoute
- When set, the connection is terminated after being handled by
server.Routes.PreRouting
- a route through which all requests will pass, useful for authentication, logging, and other functions- If defined, return
true
from this task if you wish to terminate the connection - Otherwise return
false
to allow routing to continue
- If defined, return
server.Routes.Content
- serve GET and HEAD requests for static content based on URL path- Content will be read from the
server.Routes.Content.BaseDirectory
plus the URL path - An entire directory can be listed as a content route when adding the route
- Content will be read from the
server.Routes.Static
- invoke functions based on specific HTTP method and URL combinationsserver.Routes.Parameter
- invoke functions based on specific HTTP method and URLs with embedded parameters. These values are returned inHttpContext.HttpRequest.Url.Parameters
server.Routes.Dynamic
- invoke functions based on specific HTTP method and a regular expression for the URLserver.Routes.Default
- any request that did not match a content route, static route, or dynamic route, is routed here
Additionally, you can annotate your own methods using the StaticRoute
, ParameterRoute
, or DynamicRoute
attributes. Methods decorated with these attributes must be marked as public
.
Webserver server = new Webserver("localhost", 9000, false, null, null, DefaultRoute);
server.Start();
[StaticRoute(HttpMethod.GET, "/static")]
public static async Task MyStaticRoute(HttpContext ctx)
{
string resp = "Hello from the static route";
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "text/plain";
ctx.Response.ContentLength = resp.Length;
await ctx.Response.SendAsync(resp);
return;
}
[ParameterRoute(HttpMethod.GET, "/{version}/api/{id}")]
public static async Task MyParameterRoute(HttpContext ctx)
{
string resp = "Hello from parameter route version " + ctx.Request.Url.Parameters["version"] + " for ID " + ctx.Request.Url.Parameters["id"];
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "text/plain";
ctx.Response.ContentLength = resp.Length;
await ctx.Response.SendAsync(resp);
return;
}
[DynamicRoute(HttpMethod.GET, "^/dynamic/\\d+$")]
public static async Task MyDynamicRoute(HttpContext ctx)
{
string resp = "Hello from the dynamic route";
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "text/plain";
ctx.Response.ContentLength = resp.Length;
await ctx.Response.SendAsync(resp);
return;
}
Authorizing or Declining a Connection
server.Callbacks.AuthorizeConnection = AuthorizeConnection;
private static bool AuthorizeConnection(string ipAddress, int port)
{
// evaluate the IP address and port
return true; // permit
return false; // deny
}
HostBuilder
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.
using WatsonWebserver.Extensions.HostBuilderExtension;
Server server = new HostBuilder("127.0.0.1", 8000, false, DefaultRoute)
.MapStaticRoute(WatsonWebserver.HttpMethod.GET, GetUrlsRoute, "/links")
.MapStaticRoute(WatsonWebserver.HttpMethod.POST, CheckLoginRoute, "/login")
.MapStaticRoute(WatsonWebserver.HttpMethod.POST, TestRoute, "/test")
.Build();
server.Start();
Console.WriteLine("Server started");
Console.ReadKey();
static async Task DefaultRoute(HttpContext ctx) =>
await ctx.Response.SendAsync("Hello from default route!");
static async Task GetUrlsRoute(HttpContext ctx) =>
await ctx.Response.SendAsync("Here are your links!");
static async Task CheckLoginRoute(HttpContext ctx) =>
await ctx.Response.SendAsync("Checking your login!");
static async Task TestRoute(HttpContext ctx) =>
await ctx.Response.SendAsync("Hello from the test route!");
Accessing from Outside Localhost
When you configure HttpServerLite to listen on 127.0.0.1
or localhost
, it will only respond to requests received from within the local machine.
To configure access from other nodes outside of localhost
, use the following:
- Specify the IP address on which HttpServerLite should listen in the Server constructor.
- If you want to listen on more than one IP address, use
*
or+
- If you listen on anything other than
localhost
or127.0.0.1
, you may have to run HttpServerLite as administrator (operating system dependent) - If you want to use a port number less than 1024, you MUST run HttpServerLite as administrator (this is an operating system limitation)
- Open a port on your firewall to permit traffic on the TCP port upon which HttpServerLite is listening
- 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
Version History
Refer to CHANGELOG.md for version history.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 is compatible. |
.NET Standard | netstandard2.1 is compatible. |
.NET Framework | net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 is compatible. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETCoreApp 3.1
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
-
.NETFramework 4.6.1
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
-
.NETFramework 4.8
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
-
.NETStandard 2.1
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
-
net6.0
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
-
net7.0
- CavemanTcp (>= 2.0.0)
- IpMatcher (>= 1.0.4.4)
- RegexMatcher (>= 1.0.8)
- System.Text.Json (>= 7.0.2)
- Timestamps (>= 1.0.2)
- UrlMatcher (>= 2.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.1.5 | 1,239 | 9/28/2023 |
2.1.4 | 1,859 | 8/3/2023 |
2.1.3 | 209 | 8/2/2023 |
2.1.2 | 1,918 | 7/5/2023 |
2.1.1 | 159 | 7/4/2023 |
2.1.0 | 163 | 7/4/2023 |
2.0.2 | 881 | 5/18/2023 |
2.0.1 | 134 | 5/18/2023 |
2.0.0 | 865 | 3/14/2023 |
1.2.12 | 1,164 | 1/27/2023 |
1.2.11 | 1,023 | 1/11/2023 |
1.2.10 | 1,778 | 11/26/2022 |
1.2.9 | 1,172 | 10/24/2022 |
1.2.8 | 544 | 10/12/2022 |
1.2.7 | 394 | 10/12/2022 |
1.2.6 | 2,237 | 8/8/2022 |
1.2.4 | 619 | 6/1/2022 |
1.2.3 | 619 | 5/19/2022 |
1.2.2 | 527 | 5/4/2022 |
1.2.1.11 | 563 | 4/1/2022 |
1.2.1.10 | 459 | 3/30/2022 |
1.2.1.8 | 499 | 2/18/2022 |
1.2.1.7 | 508 | 1/19/2022 |
1.2.1.6 | 532 | 1/13/2022 |
1.2.1.5 | 371 | 12/20/2021 |
1.2.1.4 | 291 | 12/20/2021 |
1.2.1.3 | 1,165 | 11/12/2021 |
1.2.1.2 | 2,180 | 10/6/2021 |
1.2.1.1 | 1,793 | 8/19/2021 |
1.2.1 | 4,117 | 2/22/2021 |
1.2.0 | 4,200 | 12/26/2020 |
1.1.0.2 | 548 | 12/26/2020 |
1.1.0.1 | 506 | 11/18/2020 |
1.0.6.1 | 441 | 11/11/2020 |
1.0.6 | 484 | 11/10/2020 |
1.0.5 | 529 | 11/9/2020 |
1.0.4 | 459 | 10/14/2020 |
1.0.3 | 470 | 10/14/2020 |
1.0.2 | 540 | 10/10/2020 |
1.0.1.1 | 1,937 | 8/30/2020 |
1.0.1 | 5,872 | 7/12/2020 |
1.0.0.16 | 1,004 | 6/30/2020 |
HostBuilder feature from @sapurtcomputer30