Skip to content

Commit

Permalink
0.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
CypherPotato committed Jan 7, 2023
1 parent 8ec95d3 commit f3766fc
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 177 deletions.
37 changes: 37 additions & 0 deletions .nuget/README.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Features</title>
</head>
<body>

<p>Sisk is a powerful framework for building powerful web applications. It is written in .NET 6 and uses Microsoft-HTTPAPI/2.0 as their main http Engine.</p>
<h2 id="features">Features</h2>
<ul>
<li>Multi-platform and cross-operating system</li>
<li>Ultra fast response/second average</li>
<li>Support to operating system's native HTTP interface listener</li>
<li>Sustainable and maintainable</li>
<li>Database-agnostic</li>
<li>Same code implementation for *nix, Mac OS and Windows</li>
<li>Asynchronous request handling</li>
<li>Middlewares, before and/or after request handlers</li>
<li>Configurable error handling</li>
<li>Support to log access/error logs</li>
<li>Easy Cross-Origin Resource Sharing setup</li>
<li>Written in C#</li>
</ul>
<blockquote>
<p>You can use Sisk with HTTPS, HTTP/2 and HTTP/3 QUIC if you follow <a href="https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis">this Microsoft tutorial</a>. Requires installation of IIS on Windows.</p>
</blockquote>
<h2 id="documentation">Documentation</h2>
<p>The specification is complete, however, tutorials are yet to come. By the way, you can access the Sisk documentation <a href="https://sisk-http.github.io/docs/static/#/">here</a>.</p>
<p>You can also view release change logs <a href="https://github.com/sisk-http/docs/blob/master/Changelog.md">here</a>.</p>
<h2 id="installation">Installation</h2>
<p>You can install the latest release from Nuget:</p>
<pre><code>PM&gt; dotnet add package Sisk.HttpServer
</code></pre>


</body>
</html>
45 changes: 22 additions & 23 deletions src/Http/HttpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ namespace Sisk.Core.Http
/// </namespace>
public class HttpServer : IDisposable
{
private Mutex _accessLogMutex = new Mutex();
private Mutex _errorLogMutex = new Mutex();
private bool _isListening = false;
private bool _isDisposing = false;

Expand Down Expand Up @@ -253,14 +255,7 @@ private void ListenerCallback(IAsyncResult result)
dnsSafeHost = forwardedHost;
}

if (ServerConfiguration.Verbose == VerboseMode.Normal)
{
verbosePrefix = $"{context.Request.HttpMethod,8} ({baseRequest.Url.Authority}) {context.Request.Url?.AbsolutePath ?? " / "}";
}
else if (ServerConfiguration.Verbose == VerboseMode.Detailed)
{
verbosePrefix = $"{context.Request.HttpMethod,8} {DateTime.Now:G} %%STATUS%% {request.Origin} ({baseRequest.Url?.Scheme} {baseRequest.Url!.Authority}) {context.Request.Url?.AbsolutePath ?? "/"}";
}
verbosePrefix = $"{DateTime.Now:g} %%STATUS%% {context.Request.HttpMethod} {request.Origin.ToString().TrimEnd('\0')} ({baseRequest.Url?.Scheme} {baseRequest.Url!.Authority}) {context.Request.Url?.AbsolutePath ?? "/"}";

// detect the listening host for this listener
ListeningHost? matchedListeningHost = ServerConfiguration.ListeningHosts
Expand Down Expand Up @@ -394,16 +389,16 @@ private void ListenerCallback(IAsyncResult result)

string httpStatusVerbose = $"{(int)response.Status} {response.Status}";

executionResult.Status = HttpServerExecutionStatus.Executed;
verboseSuffix = $"[{httpStatusVerbose}] {HumanReadableSize((int)incomingSize) + " -> " + HumanReadableSize((int)outcomingSize)}";

executionResult.RequestSize = incomingSize;
executionResult.ResponseSize = outcomingSize;
executionResult.Response = response;

sw.Stop();
baseResponse.Close();

closeStream = false;
executionResult.Status = HttpServerExecutionStatus.Executed;
verboseSuffix = $"[{httpStatusVerbose}] {HumanReadableSize((int)incomingSize) + " -> " + HumanReadableSize((int)outcomingSize)}";
}
catch (ObjectDisposedException objException)
{
Expand Down Expand Up @@ -439,27 +434,31 @@ private void ListenerCallback(IAsyncResult result)
OnConnectionClose(this, executionResult);
}

if (ServerConfiguration.Verbose == VerboseMode.Normal)
if (executionResult.ServerException != null)
{
if (!string.IsNullOrEmpty(verbosePrefix))
_errorLogMutex.WaitOne();
ServerConfiguration.ErrorsLogsStream?.WriteLine($"Exception thrown at {DateTime.Now:R}");
ServerConfiguration.ErrorsLogsStream?.WriteLine(executionResult.ServerException);
if (executionResult.ServerException.InnerException != null)
{
if (verboseSuffix == "")
{
Console.WriteLine($"{verbosePrefix} -> {executionResult.Status}");
}
else
{
Console.WriteLine($"{verbosePrefix} {verboseSuffix}");
}
ServerConfiguration.ErrorsLogsStream?.WriteLine(executionResult.ServerException.InnerException);
}
_errorLogMutex.ReleaseMutex();
}
else if (ServerConfiguration.Verbose == VerboseMode.Detailed)

if (ServerConfiguration.AccessLogsStream != null)
{
_accessLogMutex.WaitOne();
if (!string.IsNullOrEmpty(verbosePrefix))
{
verbosePrefix = verbosePrefix.Replace("%%STATUS%%", executionResult.Status.ToString());
Console.WriteLine($"{verbosePrefix} {verboseSuffix} after {sw.ElapsedMilliseconds}ms");
ServerConfiguration.AccessLogsStream.WriteLine($"{verbosePrefix} {verboseSuffix} after {sw.ElapsedMilliseconds}ms");
}
else
{
ServerConfiguration.AccessLogsStream.WriteLine($"{verbosePrefix} -> {executionResult.Status}");
}
_accessLogMutex.ReleaseMutex();
}
}
}
Expand Down
43 changes: 42 additions & 1 deletion src/Http/HttpServerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,40 @@ namespace Sisk.Core.Http
/// </namespace>
public class HttpServerConfiguration : IDisposable
{
/// <summary>
/// Gets or sets the <see cref="TextWriter"/> object which the HTTP server will write HTTP server access messages to.
/// </summary>
/// <remarks>
/// This property defaults to Console.Out. By setting this property to null, no output will be written, completely ignoring the `Verbose` property.
/// </remarks>
/// <definition>
/// public TextWriter? AccessLogsStream { get; set; }
/// </definition>
/// <type>
/// Property
/// </type>
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public TextWriter? AccessLogsStream { get; set; } = Console.Out;

/// <summary>
/// Gets or sets the <see cref="TextWriter"/> object which the HTTP server will write HTTP server error transcriptions to.
/// </summary>
/// <remarks>
/// This stream could be empty if ThrowExceptions is true.
/// </remarks>
/// <definition>
/// public TextWriter? ErrorsLogsStream { get; set; }
/// </definition>
/// <type>
/// Property
/// </type>
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public TextWriter? ErrorsLogsStream { get; set; }

/// <summary>
/// Gets or sets whether the HTTP server should resolve remote (IP) addresses by the X-Forwarded-For header. This option is useful if you are using Sisk through a reverse proxy.
/// </summary>
Expand Down Expand Up @@ -76,17 +110,22 @@ public class HttpServerConfiguration : IDisposable
public long MaximumContentLength { get; set; } = 0;

/// <summary>
/// Gets or sets the message level the console will write.
/// Gets or sets the message level the console will write. This property is now deprecated. Use <see cref="AccessLogsStream"/> or <see cref="ErrorsLogsStream"/> instead.
/// </summary>
/// <definition>
/// [Obsolete]
/// public VerboseMode Verbose { get; set; }
/// </definition>
/// <remarks>
/// Since Sisk 0.8.1, this property was deprecated. The defaults for the <see cref="AccessLogsStream"/> it's the <see cref="VerboseMode.Detailed"/> verbose mode.
/// </remarks>
/// <type>
/// Property
/// </type>
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
[Obsolete]
public VerboseMode Verbose { get; set; } = VerboseMode.Normal;

/// <summary>
Expand Down Expand Up @@ -162,6 +201,8 @@ public HttpServerConfiguration()
public void Dispose()
{
ListeningHosts.Clear();
AccessLogsStream?.Close();
ErrorsLogsStream?.Close();
}
}

Expand Down
32 changes: 21 additions & 11 deletions src/Http/ListeningHost.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Sisk.Core.Entity;
using Sisk.Core.Routing;
using System.Runtime.Serialization;

namespace Sisk.Core.Http
{
Expand All @@ -15,25 +16,25 @@ namespace Sisk.Core.Http
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public class ListeningHost
public unsafe class ListeningHost
{
private static Random handleGenerator = new Random();
private ListeningPort[] _ports = null!;
internal int[] _numericPorts = null!;

/// <summary>
/// Gets an unique handle to this router instance.
/// Gets an unique identifier to this listening host instance.
/// </summary>
/// <definition>
/// public int Handle { get; init; }
/// public long Handle { get; }
/// </definition>
/// <type>
/// Property
/// </type>
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public int Handle { get; init; } = handleGenerator.Next();
public long Handle { get; private set; }
private long _handle = 0;

/// <summary>
/// Gets whether this <see cref="ListeningHost"/> can be listened by it's host <see cref="HttpServer"/>.
Expand Down Expand Up @@ -130,6 +131,15 @@ public ListeningPort[] Ports
/// </namespace>
public Router? Router { get; set; }

private ListeningHost()
{
Hostname = null!;
fixed (long* h = &_handle)
{
Handle = (long)h;
}
}

/// <summary>
/// Creates an new <see cref="ListeningHost"/> value with given parameters.
/// </summary>
Expand All @@ -146,7 +156,7 @@ public ListeningPort[] Ports
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string hostname, int port, Router r)
public ListeningHost(string hostname, int port, Router r) : this()
{
Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
Ports = new ListeningPort[] { new ListeningPort(port) };
Expand All @@ -169,7 +179,7 @@ public ListeningHost(string hostname, int port, Router r)
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string hostname, ListeningPort port, Router r)
public ListeningHost(string hostname, ListeningPort port, Router r) : this()
{
Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
Ports = new ListeningPort[] { port };
Expand All @@ -192,7 +202,7 @@ public ListeningHost(string hostname, ListeningPort port, Router r)
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string hostname, int[] ports, Router r)
public ListeningHost(string hostname, int[] ports, Router r) : this()
{
Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
Router = r;
Expand Down Expand Up @@ -220,7 +230,7 @@ public ListeningHost(string hostname, int[] ports, Router r)
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string hostname, ListeningPort[] ports, Router r)
public ListeningHost(string hostname, ListeningPort[] ports, Router r) : this()
{
Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
Router = r;
Expand All @@ -242,7 +252,7 @@ public ListeningHost(string hostname, ListeningPort[] ports, Router r)
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string hostname, ListeningPort[] ports)
public ListeningHost(string hostname, ListeningPort[] ports) : this()
{
Hostname = hostname ?? throw new ArgumentNullException(nameof(hostname));
Ports = ports;
Expand All @@ -262,7 +272,7 @@ public ListeningHost(string hostname, ListeningPort[] ports)
/// <namespace>
/// Sisk.Core.Http
/// </namespace>
public ListeningHost(string uri, Router r)
public ListeningHost(string uri, Router r) : this()
{
Uri uriInstance = new Uri(uri);
this.Hostname = uriInstance.Host;
Expand Down
Loading

0 comments on commit f3766fc

Please sign in to comment.