-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: API enhancements, add custom experimental httplistener
- Loading branch information
1 parent
1148fd8
commit 93f8ad8
Showing
19 changed files
with
692 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace Sisk.ManagedHttpListener; | ||
|
||
public delegate void HttpAction(HttpSession session); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
using Sisk.ManagedHttpListener.HttpSerializer; | ||
|
||
namespace Sisk.ManagedHttpListener; | ||
|
||
public sealed class HttpConnection : IDisposable | ||
{ | ||
private readonly Stream _connectionStream; | ||
private bool disposedValue; | ||
|
||
public HttpAction Action { get; set; } | ||
|
||
public HttpConnection(Stream connectionStream, HttpAction action) | ||
{ | ||
_connectionStream = connectionStream; | ||
Action = action; | ||
} | ||
|
||
public int HandleConnectionEvents() | ||
{ | ||
ObjectDisposedException.ThrowIf(disposedValue, this); | ||
|
||
Span<byte> memRequestLine = stackalloc byte[8192]; | ||
|
||
while (_connectionStream.CanRead && !disposedValue) | ||
{ | ||
//try | ||
//{ | ||
using var bufferedStreamSession = new Streams.HttpBufferedStream(_connectionStream); | ||
|
||
if (!HttpRequestSerializer.TryReadHttp1Request( | ||
bufferedStreamSession, | ||
memRequestLine, | ||
out var method, | ||
out var path, | ||
out var reqContentLength, | ||
out var messageSize, | ||
out var headers, | ||
out var expectContinue)) | ||
{ | ||
Logger.LogInformation($"couldn't read request"); | ||
return 1; | ||
} | ||
|
||
HttpSession.HttpRequest managedRequest = new HttpSession.HttpRequest(method, path, reqContentLength, headers, _connectionStream); | ||
HttpSession managedSession = new HttpSession(managedRequest, _connectionStream); | ||
|
||
Action(managedSession); | ||
|
||
if (!managedSession.KeepAlive) | ||
managedSession.Response.Headers.Set(("Connection", "Close")); | ||
|
||
Stream? responseStream = managedSession.Response.ResponseStream; | ||
if (responseStream is not null) | ||
{ | ||
if (responseStream.CanSeek) | ||
{ | ||
managedSession.Response.Headers.Set(("Content-Length", responseStream.Length.ToString())); | ||
} | ||
else | ||
{ | ||
// implement chunked-encodind | ||
} | ||
} | ||
else | ||
{ | ||
managedSession.Response.Headers.Set(("Content-Length", "0")); | ||
} | ||
|
||
if (!HttpResponseSerializer.TryWriteHttp1Response( | ||
_connectionStream, | ||
managedSession.Response.StatusCode, | ||
managedSession.Response.StatusDescription, | ||
managedSession.Response.Headers)) | ||
{ | ||
Logger.LogInformation($"couldn't write response"); | ||
return 2; | ||
} | ||
|
||
if (responseStream is not null) | ||
{ | ||
responseStream.CopyTo(_connectionStream); | ||
responseStream.Dispose(); | ||
} | ||
|
||
_connectionStream.Flush(); | ||
|
||
if (!managedSession.KeepAlive) | ||
{ | ||
break; | ||
} | ||
//} | ||
//catch (Exception ex) | ||
//{ | ||
// Logger.LogInformation($"unhandled exception: {ex.Message}"); | ||
// return 3; | ||
//} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
private void Dispose(bool disposing) | ||
{ | ||
if (!disposedValue) | ||
{ | ||
if (disposing) | ||
{ | ||
_connectionStream.Dispose(); | ||
} | ||
|
||
disposedValue = true; | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(disposing: true); | ||
GC.SuppressFinalize(this); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// The Sisk Framework source code | ||
// Copyright (c) 2023 PROJECT PRINCIPIUM | ||
// | ||
// The code below is licensed under the MIT license as | ||
// of the date of its publication, available at | ||
// | ||
// File name: HttpHeaderExtensions.cs | ||
// Repository: https://github.com/sisk-http/core | ||
|
||
namespace Sisk.ManagedHttpListener; | ||
|
||
internal static class HttpHeaderExtensions | ||
{ | ||
public static void Set(this List<(string, string)> headers, (string, string) header) | ||
{ | ||
for (int i = headers.Count - 1; i >= 0; i--) | ||
{ | ||
if (StringComparer.OrdinalIgnoreCase.Compare(headers[i].Item1, header.Item1) == 0) | ||
{ | ||
headers.RemoveAt(i); | ||
} | ||
} | ||
|
||
headers.Add(header); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System.Net; | ||
using System.Net.Sockets; | ||
|
||
namespace Sisk.ManagedHttpListener; | ||
|
||
public sealed class HttpHost : IDisposable | ||
{ | ||
private readonly TcpListener _listener; | ||
private bool disposedValue; | ||
|
||
public HttpAction ActionHandler { get; } | ||
public bool IsDisposed { get => disposedValue; } | ||
public int Port { get; set; } = 8080; | ||
|
||
public HttpHost(int port, HttpAction actionHandler) | ||
{ | ||
_listener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); | ||
ActionHandler = actionHandler; | ||
} | ||
|
||
public void Start() | ||
{ | ||
ObjectDisposedException.ThrowIf(disposedValue, this); | ||
|
||
_listener.Start(); | ||
_listener.BeginAcceptTcpClient(ReceiveClient, null); | ||
} | ||
|
||
private void ReceiveClient(IAsyncResult result) | ||
{ | ||
_listener.BeginAcceptTcpClient(ReceiveClient, null); | ||
using (TcpClient client = _listener.EndAcceptTcpClient(result)) | ||
{ | ||
Stream clientStream = client.GetStream(); | ||
|
||
using (HttpConnection connection = new HttpConnection(clientStream, ActionHandler)) | ||
{ | ||
connection.HandleConnectionEvents(); | ||
} | ||
} | ||
} | ||
|
||
private void Dispose(bool disposing) | ||
{ | ||
if (!disposedValue) | ||
{ | ||
if (disposing) | ||
{ | ||
_listener.Dispose(); | ||
} | ||
|
||
disposedValue = true; | ||
} | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||
Dispose(disposing: true); | ||
GC.SuppressFinalize(this); | ||
} | ||
} |
Oops, something went wrong.