From 337b97384a85e54efb8a95dcbd9ca85a9259550e Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 16:44:54 +0100 Subject: [PATCH 1/7] Move the Header fields from the document to the task. --- MaxLib.WebServer.Test/Testing/TestTestTask.cs | 2 +- MaxLib.WebServer/Api/ApiService.cs | 6 +-- MaxLib.WebServer/Api/Rest/RestApiService.cs | 4 +- .../Chunked/ChunkedResponseCreator.cs | 4 +- MaxLib.WebServer/Chunked/ChunkedSender.cs | 4 +- MaxLib.WebServer/HttpDocument.cs | 7 +++- MaxLib.WebServer/Lazy/LazyTask.cs | 2 +- MaxLib.WebServer/MultipartRanges.cs | 39 ++++++++++++++----- MaxLib.WebServer/Server.cs | 8 +--- MaxLib.WebServer/Services/Http404Service.cs | 12 +++--- .../Services/HttpDirectoryMapper.cs | 6 +-- .../Services/HttpDocumentFinder.cs | 4 +- MaxLib.WebServer/Services/HttpHeaderParser.cs | 16 ++++---- .../Services/HttpHeaderPostParser.cs | 2 +- .../Services/HttpHeaderSpecialAction.cs | 4 +- .../Services/HttpResponseCreator.cs | 4 +- MaxLib.WebServer/Services/HttpSender.cs | 4 +- .../Services/StandardDocumentLoader.cs | 2 +- .../Sessions/SessionServiceBase.cs | 4 +- MaxLib.WebServer/Testing/TestTask.cs | 12 +++--- MaxLib.WebServer/WebProgressTask.cs | 9 ++++- MaxLib.WebServer/WebServerTaskCreator.cs | 28 ++++++------- 22 files changed, 103 insertions(+), 80 deletions(-) diff --git a/MaxLib.WebServer.Test/Testing/TestTestTask.cs b/MaxLib.WebServer.Test/Testing/TestTestTask.cs index 1b62ff3..fc8330e 100644 --- a/MaxLib.WebServer.Test/Testing/TestTestTask.cs +++ b/MaxLib.WebServer.Test/Testing/TestTestTask.cs @@ -12,7 +12,7 @@ public void TestGetAddedCookies() { var server = new TestWebServer(); var test = new TestTask(server); - test.Task.Document.RequestHeader.Cookie.AddedCookies.Add( + test.Task.Request.Cookie.AddedCookies.Add( "test1", new MaxLib.WebServer.HttpCookie.Cookie("test2", "test3")); var added = test.GetAddedCookies().ToArray(); diff --git a/MaxLib.WebServer/Api/ApiService.cs b/MaxLib.WebServer/Api/ApiService.cs index 17240c9..48b554a 100644 --- a/MaxLib.WebServer/Api/ApiService.cs +++ b/MaxLib.WebServer/Api/ApiService.cs @@ -25,19 +25,19 @@ public string[] Endpoint public override bool CanWorkWith(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - return task.Document.RequestHeader.Location.StartsUrlWith(endpoint, IgnoreCase); + return task.Request.Location.StartsUrlWith(endpoint, IgnoreCase); } public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var tiles = task.Document.RequestHeader.Location.DocumentPathTiles; + var tiles = task.Request.Location.DocumentPathTiles; var location = new string[tiles.Length - endpoint.Length]; Array.Copy(tiles, endpoint.Length, location, 0, location.Length); var data = await HandleRequest(task, location); if (data != null) task.Document.DataSources.Add(data); - else task.Document.ResponseHeader.StatusCode = HttpStateCode.InternalServerError; + else task.Response.StatusCode = HttpStateCode.InternalServerError; } } } diff --git a/MaxLib.WebServer/Api/Rest/RestApiService.cs b/MaxLib.WebServer/Api/Rest/RestApiService.cs index 2d8587c..922bcda 100644 --- a/MaxLib.WebServer/Api/Rest/RestApiService.cs +++ b/MaxLib.WebServer/Api/Rest/RestApiService.cs @@ -33,14 +33,14 @@ protected virtual RestQueryArgs GetQueryArgs(WebProgressTask task, string[] loca { _ = task ?? throw new ArgumentNullException(nameof(task)); _ = location ?? throw new ArgumentNullException(nameof(location)); - return new RestQueryArgs(location, task.Document.RequestHeader.Location.GetParameter, task.Document.RequestHeader.Post); + return new RestQueryArgs(location, task.Request.Location.GetParameter, task.Request.Post); } protected virtual HttpDataSource NoEndpoint(WebProgressTask task, RestQueryArgs args) { _ = task ?? throw new ArgumentNullException(nameof(task)); _ = args ?? throw new ArgumentNullException(nameof(args)); - task.Document.ResponseHeader.StatusCode = HttpStateCode.NotFound; + task.Response.StatusCode = HttpStateCode.NotFound; return new HttpStringDataSource("no endpoint"); } } diff --git a/MaxLib.WebServer/Chunked/ChunkedResponseCreator.cs b/MaxLib.WebServer/Chunked/ChunkedResponseCreator.cs index db7518b..cd06529 100644 --- a/MaxLib.WebServer/Chunked/ChunkedResponseCreator.cs +++ b/MaxLib.WebServer/Chunked/ChunkedResponseCreator.cs @@ -26,8 +26,8 @@ public override bool CanWorkWith(WebProgressTask task) public override async Task ProgressTask(WebProgressTask task) { - var request = task.Document.RequestHeader; - var response = task.Document.ResponseHeader; + var request = task.Request; + var response = task.Response; response.FieldContentType = task.Document.PrimaryMime; response.SetActualDate(); response.HttpProtocol = request.HttpProtocol; diff --git a/MaxLib.WebServer/Chunked/ChunkedSender.cs b/MaxLib.WebServer/Chunked/ChunkedSender.cs index bf8615a..d3df031 100644 --- a/MaxLib.WebServer/Chunked/ChunkedSender.cs +++ b/MaxLib.WebServer/Chunked/ChunkedSender.cs @@ -28,7 +28,7 @@ public override bool CanWorkWith(WebProgressTask task) public override async Task ProgressTask(WebProgressTask task) { - var header = task.Document.ResponseHeader; + var header = task.Response; var stream = task.NetworkStream; var writer = new StreamWriter(stream); await writer.WriteAsync(header.HttpProtocol); @@ -43,7 +43,7 @@ public override async Task ProgressTask(WebProgressTask task) await writer.WriteAsync(": "); await writer.WriteLineAsync(e.Value); } - foreach (var cookie in task.Document.RequestHeader.Cookie.AddedCookies) //Cookies + foreach (var cookie in task.Request.Cookie.AddedCookies) //Cookies { await writer.WriteAsync("Set-Cookie: "); await writer.WriteLineAsync(cookie.ToString()); diff --git a/MaxLib.WebServer/HttpDocument.cs b/MaxLib.WebServer/HttpDocument.cs index b183804..ce22d83 100644 --- a/MaxLib.WebServer/HttpDocument.cs +++ b/MaxLib.WebServer/HttpDocument.cs @@ -16,9 +16,12 @@ public string PrimaryMime public string PrimaryEncoding { get; set; } = null; - public HttpRequestHeader RequestHeader { get; set; } + [Obsolete("Use WebProgressTask.Request. this will be removed in a future release.")] + public HttpRequestHeader RequestHeader { get; set; } = new HttpRequestHeader(); - public HttpResponseHeader ResponseHeader { get; set; } + [Obsolete("Use WebProgressTask.Response. this will be removed in a future release.")] + public HttpResponseHeader ResponseHeader { get; set; } = new HttpResponseHeader(); + public Dictionary Information { get; } = new Dictionary(); public object this[object identifer] diff --git a/MaxLib.WebServer/Lazy/LazyTask.cs b/MaxLib.WebServer/Lazy/LazyTask.cs index 654e7c3..2189472 100644 --- a/MaxLib.WebServer/Lazy/LazyTask.cs +++ b/MaxLib.WebServer/Lazy/LazyTask.cs @@ -26,7 +26,7 @@ public LazyTask(WebProgressTask task) _ = task ?? throw new ArgumentNullException(nameof(task)); Server = task.Server; Connection = task.Connection; - Header = task.Document.RequestHeader; + Header = task.Request; Information = task.Document.Information; } } diff --git a/MaxLib.WebServer/MultipartRanges.cs b/MaxLib.WebServer/MultipartRanges.cs index 95835ce..f132f13 100644 --- a/MaxLib.WebServer/MultipartRanges.cs +++ b/MaxLib.WebServer/MultipartRanges.cs @@ -50,26 +50,47 @@ public string ToString(long total) readonly List streams = new List(); readonly Stream baseStream; - readonly HttpDocument document; + // readonly HttpDocument document; + readonly HttpResponseHeader response; List ranges = new List(); + [Obsolete("Use MultipartRanges(Stream, HttpRequestHeader, HttpResponseHeader, string) instead. This will be removed in a future release.")] public MultipartRanges(Stream stream, HttpDocument document, string mime) + : this(stream, document.RequestHeader, document.ResponseHeader, mime) { - this.document = document ?? throw new ArgumentNullException(nameof(document)); + + } + + public MultipartRanges(Stream stream, WebProgressTask task, string mime) + : this( + stream, + task?.Request ?? throw new ArgumentNullException(nameof(task.Request)), + task?.Response ?? throw new ArgumentNullException(nameof(task.Response)), + mime + ) + { + + } + + public MultipartRanges(Stream stream, HttpRequestHeader request, + HttpResponseHeader response, string mime) + { + _ = request ?? throw new ArgumentNullException(nameof(request)); + this.response = response ?? throw new ArgumentNullException(nameof(response)); baseStream = stream ?? throw new ArgumentNullException(nameof(stream)); MimeType = mime; - document.ResponseHeader.HeaderParameter["Accept-Ranges"] = "bytes"; - if (document.RequestHeader.HeaderParameter.ContainsKey("Range")) + response.HeaderParameter["Accept-Ranges"] = "bytes"; + if (request.HeaderParameter.ContainsKey("Range")) { - ParseRanges(document.RequestHeader.HeaderParameter["Range"]); + ParseRanges(response.HeaderParameter["Range"]); var valid = ranges.Count > 0; foreach (var r in ranges) if (r.From < 0 || r.From >= baseStream.Length || r.To < 0 || r.To >= baseStream.Length) valid = false; if (!valid) { - document.ResponseHeader.StatusCode = HttpStateCode.RequestedRangeNotSatisfiable; + response.StatusCode = HttpStateCode.RequestedRangeNotSatisfiable; return; } FormatRanges(); @@ -138,8 +159,8 @@ void FormatRanges() void SinglePart() { - document.ResponseHeader.StatusCode = HttpStateCode.PartialContent; - var h = document.ResponseHeader.HeaderParameter; + response.StatusCode = HttpStateCode.PartialContent; + var h = response.HeaderParameter; h["Content-Range"] = ranges[0].ToString(baseStream.Length); streams.Add(new HttpStreamDataSource(baseStream) { @@ -155,7 +176,7 @@ void MultiPart() new Random().NextBytes(b); var boundary = BitConverter.ToString(b).Replace("-", ""); base.MimeType = WebServer.MimeType.MultipartByteranges + "; boundary=" + boundary; - document.ResponseHeader.StatusCode = HttpStateCode.PartialContent; + response.StatusCode = HttpStateCode.PartialContent; var sb = new StringBuilder(); foreach (var r in ranges) { diff --git a/MaxLib.WebServer/Server.cs b/MaxLib.WebServer/Server.cs index 5cef699..62a35d5 100644 --- a/MaxLib.WebServer/Server.cs +++ b/MaxLib.WebServer/Server.cs @@ -193,7 +193,7 @@ protected virtual async Task ClientStartListen(HttpConnection connection) await ExecuteTaskChain(task); - if (task.Document.RequestHeader.FieldConnection == HttpConnectionType.KeepAlive) + if (task.Request.FieldConnection == HttpConnectionType.KeepAlive) { if (!KeepAliveConnections.Contains(connection)) KeepAliveConnections.Add(connection); @@ -244,11 +244,7 @@ protected virtual WebProgressTask PrepairProgressTask(HttpConnection connection) { CurrentStage = ServerStage.FIRST_STAGE, NextStage = (ServerStage)((int)ServerStage.FIRST_STAGE + 1), - Document = new HttpDocument - { - RequestHeader = new HttpRequestHeader(), - ResponseHeader = new HttpResponseHeader(), - }, + Document = new HttpDocument(), Server = this, Connection = connection, NetworkStream = stream, diff --git a/MaxLib.WebServer/Services/Http404Service.cs b/MaxLib.WebServer/Services/Http404Service.cs index 886ee45..b658dac 100644 --- a/MaxLib.WebServer/Services/Http404Service.cs +++ b/MaxLib.WebServer/Services/Http404Service.cs @@ -18,19 +18,19 @@ public override bool CanWorkWith(WebProgressTask task) public override Task ProgressTask(WebProgressTask task) { - task.Document.ResponseHeader.StatusCode = HttpStateCode.NotFound; + task.Response.StatusCode = HttpStateCode.NotFound; var sb = new StringBuilder(); sb.Append("404 NOT FOUND"); sb.Append("

Error 404: Not Found

The requested resource is not found.

"); sb.AppendLine("
");
-            sb.AppendLine($"Protocol: {WebUtility.HtmlEncode(task.Document.RequestHeader.HttpProtocol)}");
-            sb.AppendLine($"Method:   {WebUtility.HtmlEncode(task.Document.RequestHeader.ProtocolMethod)}");
-            sb.AppendLine($"Url:      {WebUtility.HtmlEncode(task.Document.RequestHeader.Location.Url)}");
+            sb.AppendLine($"Protocol: {WebUtility.HtmlEncode(task.Request.HttpProtocol)}");
+            sb.AppendLine($"Method:   {WebUtility.HtmlEncode(task.Request.ProtocolMethod)}");
+            sb.AppendLine($"Url:      {WebUtility.HtmlEncode(task.Request.Location.Url)}");
             sb.AppendLine($"Header:");
-            foreach (var (key, value) in task.Document.RequestHeader.HeaderParameter)
+            foreach (var (key, value) in task.Request.HeaderParameter)
                 sb.AppendLine($"\t{WebUtility.HtmlEncode(key)}: {WebUtility.HtmlEncode(value)}");
             sb.AppendLine($"Body:");
-            sb.AppendLine(WebUtility.HtmlEncode(task.Document.RequestHeader.Post.CompletePost));
+            sb.AppendLine(WebUtility.HtmlEncode(task.Request.Post.CompletePost));
             sb.Append($"

Try to change the request to get your expected response.

"); sb.Append($"Created by MaxLib.WebServer: {DateTime.UtcNow:r}"); diff --git a/MaxLib.WebServer/Services/HttpDirectoryMapper.cs b/MaxLib.WebServer/Services/HttpDirectoryMapper.cs index 119dbf9..5b0af27 100644 --- a/MaxLib.WebServer/Services/HttpDirectoryMapper.cs +++ b/MaxLib.WebServer/Services/HttpDirectoryMapper.cs @@ -61,12 +61,12 @@ public override async Task ProgressTask(WebProgressTask task) MimeType = GetMime(Path.GetExtension(path), task) }; task.Document.DataSources.Add(source); - task.Document.ResponseHeader.StatusCode = HttpStateCode.OK; + task.Response.StatusCode = HttpStateCode.OK; } if (MapFolderToo && task.Document.Information.ContainsKey("HttpDocumentFolder")) { var path = task.Document.Information["HttpDocumentFolder"].ToString(); - var url = task.Document.RequestHeader.Location.DocumentPath.TrimEnd('/'); + var url = task.Request.Location.DocumentPath.TrimEnd('/'); var d = new DirectoryInfo(path); var html = "" + d.Name + ""; html += "

" + path + "

Eine Ebene höher
    "; @@ -82,7 +82,7 @@ public override async Task ProgressTask(WebProgressTask task) MimeType = MimeType.TextHtml }; task.Document.DataSources.Add(source); - task.Document.ResponseHeader.StatusCode = HttpStateCode.OK; + task.Response.StatusCode = HttpStateCode.OK; } await Task.CompletedTask; } diff --git a/MaxLib.WebServer/Services/HttpDocumentFinder.cs b/MaxLib.WebServer/Services/HttpDocumentFinder.cs index e13b4ac..1a12a73 100644 --- a/MaxLib.WebServer/Services/HttpDocumentFinder.cs +++ b/MaxLib.WebServer/Services/HttpDocumentFinder.cs @@ -69,7 +69,7 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var path = task.Document.RequestHeader.Location.DocumentPathTiles; + var path = task.Request.Location.DocumentPathTiles; var rule = new List(); var level = -1; for (int i = 0; i < Rules.Count; ++i) @@ -85,7 +85,7 @@ public override async Task ProgressTask(WebProgressTask task) } foreach (var r in rule) { - var url = task.Document.RequestHeader.Location.DocumentPathTiles; + var url = task.Request.Location.DocumentPathTiles; var p = r.LocalMappedPath; for (int i = r.UrlMappedPath.Length; i < url.Length; ++i) p += "\\" + url[i]; if (r.File) diff --git a/MaxLib.WebServer/Services/HttpHeaderParser.cs b/MaxLib.WebServer/Services/HttpHeaderParser.cs index 869f865..1f18974 100644 --- a/MaxLib.WebServer/Services/HttpHeaderParser.cs +++ b/MaxLib.WebServer/Services/HttpHeaderParser.cs @@ -23,7 +23,7 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var header = task.Document.RequestHeader; + var header = task.Request; var stream = task.NetworkStream; var reader = new StreamReader(stream); var mwt = 50; @@ -50,9 +50,9 @@ public override async Task ProgressTask(WebProgressTask task) { if (stream is NetworkStream ns && !ns.DataAvailable) { - task.Document.RequestHeader.FieldConnection = HttpConnectionType.KeepAlive; + task.Request.FieldConnection = HttpConnectionType.KeepAlive; WebServerLog.Add(ServerLogType.Error, GetType(), "Header", "Request Time out"); - task.Document.ResponseHeader.StatusCode = HttpStateCode.RequestTimeOut; + task.Response.StatusCode = HttpStateCode.RequestTimeOut; task.NextStage = ServerStage.CreateResponse; return; } @@ -60,7 +60,7 @@ public override async Task ProgressTask(WebProgressTask task) catch (ObjectDisposedException) { WebServerLog.Add(ServerLogType.Error, GetType(), "Header", "Connection closed by remote host"); - task.Document.ResponseHeader.StatusCode = HttpStateCode.RequestTimeOut; + task.Response.StatusCode = HttpStateCode.RequestTimeOut; task.NextStage = task.CurrentStage = ServerStage.FINAL_STAGE; return; } @@ -70,14 +70,14 @@ public override async Task ProgressTask(WebProgressTask task) catch { WebServerLog.Add(ServerLogType.Error, GetType(), "Header", "Connection closed by remote host"); - task.Document.ResponseHeader.StatusCode = HttpStateCode.RequestTimeOut; + task.Response.StatusCode = HttpStateCode.RequestTimeOut; task.NextStage = task.CurrentStage = ServerStage.FINAL_STAGE; return; } if (line == null) { WebServerLog.Add(ServerLogType.Error, GetType(), "Header", "Can't read Header line"); - task.Document.ResponseHeader.StatusCode = HttpStateCode.BadRequest; + task.Response.StatusCode = HttpStateCode.BadRequest; task.NextStage = ServerStage.CreateResponse; return; } @@ -104,7 +104,7 @@ public override async Task ProgressTask(WebProgressTask task) catch { WebServerLog.Add(ServerLogType.Error, GetType(), "Header", "Bad Request"); - task.Document.ResponseHeader.StatusCode = HttpStateCode.BadRequest; + task.Response.StatusCode = HttpStateCode.BadRequest; task.NextStage = ServerStage.CreateResponse; return; } @@ -128,7 +128,7 @@ public override async Task ProgressTask(WebProgressTask task) sb.AppendLine(WebServerUtils.GetDateString(DateTime.Now) + " " + task.Connection.NetworkClient.Client.RemoteEndPoint.ToString()); var host = header.HeaderParameter.ContainsKey("Host") ? header.HeaderParameter["Host"] : ""; - sb.AppendLine(" " + host + task.Document.RequestHeader.Location.DocumentPath); + sb.AppendLine(" " + host + task.Request.Location.DocumentPath); sb.AppendLine(); lock (lockRequestFile) File.AppendAllText("requests.txt", sb.ToString()); } diff --git a/MaxLib.WebServer/Services/HttpHeaderPostParser.cs b/MaxLib.WebServer/Services/HttpHeaderPostParser.cs index 2117318..a5d26b1 100644 --- a/MaxLib.WebServer/Services/HttpHeaderPostParser.cs +++ b/MaxLib.WebServer/Services/HttpHeaderPostParser.cs @@ -23,7 +23,7 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var header = task.Document.RequestHeader; + var header = task.Request; //Accept if (header.HeaderParameter.TryGetValue("Accept", out string value)) { diff --git a/MaxLib.WebServer/Services/HttpHeaderSpecialAction.cs b/MaxLib.WebServer/Services/HttpHeaderSpecialAction.cs index 1408bf2..f152c99 100644 --- a/MaxLib.WebServer/Services/HttpHeaderSpecialAction.cs +++ b/MaxLib.WebServer/Services/HttpHeaderSpecialAction.cs @@ -17,7 +17,7 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - switch (task.Document.RequestHeader.ProtocolMethod) + switch (task.Request.ProtocolMethod) { case HttpProtocollMethod.Head: task.Document.Information["Only Header"] = true; @@ -42,7 +42,7 @@ public override bool CanWorkWith(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - switch (task.Document.RequestHeader.ProtocolMethod) + switch (task.Request.ProtocolMethod) { case HttpProtocollMethod.Head: return true; case HttpProtocollMethod.Options: return true; diff --git a/MaxLib.WebServer/Services/HttpResponseCreator.cs b/MaxLib.WebServer/Services/HttpResponseCreator.cs index 0feb3c8..6e47616 100644 --- a/MaxLib.WebServer/Services/HttpResponseCreator.cs +++ b/MaxLib.WebServer/Services/HttpResponseCreator.cs @@ -18,8 +18,8 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var request = task.Document.RequestHeader; - var response = task.Document.ResponseHeader; + var request = task.Request; + var response = task.Response; response.FieldContentType = task.Document.PrimaryMime; response.SetActualDate(); response.HttpProtocol = request.HttpProtocol; diff --git a/MaxLib.WebServer/Services/HttpSender.cs b/MaxLib.WebServer/Services/HttpSender.cs index bcca47d..ad3c8c7 100644 --- a/MaxLib.WebServer/Services/HttpSender.cs +++ b/MaxLib.WebServer/Services/HttpSender.cs @@ -90,7 +90,7 @@ public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var header = task.Document.ResponseHeader; + var header = task.Response; var stream = task.NetworkStream; var writer = new StreamWriter(stream); await writer.WriteAsync(header.HttpProtocol); @@ -105,7 +105,7 @@ public override async Task ProgressTask(WebProgressTask task) await writer.WriteAsync(": "); await writer.WriteLineAsync(e.Value); } - foreach (var cookie in task.Document.RequestHeader.Cookie.AddedCookies) //Cookies + foreach (var cookie in task.Request.Cookie.AddedCookies) //Cookies { await writer.WriteAsync("Set-Cookie: "); await writer.WriteLineAsync(cookie.Value.ToString()); diff --git a/MaxLib.WebServer/Services/StandardDocumentLoader.cs b/MaxLib.WebServer/Services/StandardDocumentLoader.cs index 3620b61..6bc4b05 100644 --- a/MaxLib.WebServer/Services/StandardDocumentLoader.cs +++ b/MaxLib.WebServer/Services/StandardDocumentLoader.cs @@ -30,7 +30,7 @@ public override async Task ProgressTask(WebProgressTask task) { MimeType = MimeType.TextHtml }; - task.Document.ResponseHeader.StatusCode = HttpStateCode.OK; + task.Response.StatusCode = HttpStateCode.OK; task.Document.DataSources.Add(source); task.Document.PrimaryEncoding = "utf-8"; diff --git a/MaxLib.WebServer/Sessions/SessionServiceBase.cs b/MaxLib.WebServer/Sessions/SessionServiceBase.cs index 706a06c..8a66c91 100644 --- a/MaxLib.WebServer/Sessions/SessionServiceBase.cs +++ b/MaxLib.WebServer/Sessions/SessionServiceBase.cs @@ -25,12 +25,12 @@ public override bool CanWorkWith(WebProgressTask task) public override async Task ProgressTask(WebProgressTask task) { _ = task ?? throw new ArgumentNullException(nameof(task)); - var cookie = task.Document?.RequestHeader.Cookie.Get("Session"); + var cookie = task.Request?.Cookie.Get("Session"); string key; if (cookie == null) { key = await GenerateSessionKey(); - task.Document?.RequestHeader.Cookie.AddedCookies.Add("Session", + task.Request?.Cookie.AddedCookies.Add("Session", new HttpCookie.Cookie( "Session", key, diff --git a/MaxLib.WebServer/Testing/TestTask.cs b/MaxLib.WebServer/Testing/TestTask.cs index 71be439..921eba9 100644 --- a/MaxLib.WebServer/Testing/TestTask.cs +++ b/MaxLib.WebServer/Testing/TestTask.cs @@ -77,22 +77,22 @@ public object GetInfoObject(object key) => Task.Document.Information.TryGetValue(key, out object value) ? value : default; public HttpStateCode GetStatusCode() - => Task.Document.ResponseHeader.StatusCode; + => Task.Response.StatusCode; public string GetRequestHeader(string key) - => Task.Document.RequestHeader.HeaderParameter.TryGetValue(key, out string value) ? value : default; + => Task.Request.HeaderParameter.TryGetValue(key, out string value) ? value : default; public string GetResponseHeader(string key) - => Task.Document.ResponseHeader.HeaderParameter.TryGetValue(key, out string value) ? value : default; + => Task.Response.HeaderParameter.TryGetValue(key, out string value) ? value : default; public IEnumerable<(string, HttpCookie.Cookie)> GetAddedCookies() - => Task.Document.RequestHeader.Cookie.AddedCookies + => Task.Request.Cookie.AddedCookies .Select(p => (p.Key, p.Value)); public HttpRequestHeader Request - => Task.Document.RequestHeader; + => Task.Request; public HttpResponseHeader Response - => Task.Document.ResponseHeader; + => Task.Response; } } diff --git a/MaxLib.WebServer/WebProgressTask.cs b/MaxLib.WebServer/WebProgressTask.cs index 0268c9f..9583381 100644 --- a/MaxLib.WebServer/WebProgressTask.cs +++ b/MaxLib.WebServer/WebProgressTask.cs @@ -1,4 +1,5 @@ -using System; +using System.Net; +using System; #nullable enable @@ -27,6 +28,12 @@ public class WebProgressTask : IDisposable public Sessions.Session? Session { get; set; } +#pragma warning disable CS0618 + public HttpRequestHeader? Request => Document?.RequestHeader; + + public HttpResponseHeader? Response => Document?.ResponseHeader; +#pragma warning restore CS0618 + public void Dispose() { Document?.Dispose(); diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs index 0a09da5..2120761 100644 --- a/MaxLib.WebServer/WebServerTaskCreator.cs +++ b/MaxLib.WebServer/WebServerTaskCreator.cs @@ -15,11 +15,7 @@ public WebServerTaskCreator() Task = new WebProgressTask() { CurrentStage = ServerStage.FIRST_STAGE, - Document = new HttpDocument() - { - RequestHeader = new HttpRequestHeader(), - ResponseHeader = new HttpResponseHeader(), - }, + Document = new HttpDocument(), Connection = new HttpConnection { Ip = "127.0.0.1", @@ -40,37 +36,37 @@ public async Task Start(Server server) public void SetProtocolHeader(string url, string method = "GET", string protocol = "HTTP/1.1") { - Task.Document.RequestHeader.ProtocolMethod = method; - Task.Document.RequestHeader.Url = url; - Task.Document.RequestHeader.HttpProtocol = protocol; + Task.Request.ProtocolMethod = method; + Task.Request.Url = url; + Task.Request.HttpProtocol = protocol; } public void SetHeaderParameter(string key, string value) { - if (Task.Document.RequestHeader.HeaderParameter.ContainsKey(key)) - Task.Document.RequestHeader.HeaderParameter[key] = value; - else Task.Document.RequestHeader.HeaderParameter.Add(key, value); + if (Task.Request.HeaderParameter.ContainsKey(key)) + Task.Request.HeaderParameter[key] = value; + else Task.Request.HeaderParameter.Add(key, value); } public void SetPost(string post, string mime) { - Task.Document.RequestHeader.Post.SetPost(post, mime); + Task.Request.Post.SetPost(post, mime); } public void SetAccept(string[] acceptTypes = null, string[] encoding = null) { - if (acceptTypes != null) Task.Document.RequestHeader.FieldAccept.AddRange(acceptTypes); - if (encoding != null) Task.Document.RequestHeader.FieldAcceptEncoding.AddRange(acceptTypes); + if (acceptTypes != null) Task.Request.FieldAccept.AddRange(acceptTypes); + if (encoding != null) Task.Request.FieldAcceptEncoding.AddRange(acceptTypes); } public void SetHost(string host) { - Task.Document.RequestHeader.Host = host; + Task.Request.Host = host; } public void SetCookie(string cookieString) { - Task.Document.RequestHeader.Cookie.SetRequestCookieString(cookieString); + Task.Request.Cookie.SetRequestCookieString(cookieString); } public void SetStream(Stream stream) From 03a32f5718dfb02fca56f85a292a44884a3d26c9 Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 16:48:36 +0100 Subject: [PATCH 2/7] Make WebProgressTask.Document readonly --- MaxLib.WebServer/Server.cs | 1 - MaxLib.WebServer/WebProgressTask.cs | 6 +++--- MaxLib.WebServer/WebServerTaskCreator.cs | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/MaxLib.WebServer/Server.cs b/MaxLib.WebServer/Server.cs index 62a35d5..3e0681e 100644 --- a/MaxLib.WebServer/Server.cs +++ b/MaxLib.WebServer/Server.cs @@ -244,7 +244,6 @@ protected virtual WebProgressTask PrepairProgressTask(HttpConnection connection) { CurrentStage = ServerStage.FIRST_STAGE, NextStage = (ServerStage)((int)ServerStage.FIRST_STAGE + 1), - Document = new HttpDocument(), Server = this, Connection = connection, NetworkStream = stream, diff --git a/MaxLib.WebServer/WebProgressTask.cs b/MaxLib.WebServer/WebProgressTask.cs index 9583381..feb767e 100644 --- a/MaxLib.WebServer/WebProgressTask.cs +++ b/MaxLib.WebServer/WebProgressTask.cs @@ -7,7 +7,7 @@ namespace MaxLib.WebServer { public class WebProgressTask : IDisposable { - public HttpDocument? Document { get; set; } + public HttpDocument Document { get; } = new HttpDocument(); public System.IO.Stream? NetworkStream { get; set; } @@ -29,9 +29,9 @@ public class WebProgressTask : IDisposable public Sessions.Session? Session { get; set; } #pragma warning disable CS0618 - public HttpRequestHeader? Request => Document?.RequestHeader; + public HttpRequestHeader Request => Document.RequestHeader; - public HttpResponseHeader? Response => Document?.ResponseHeader; + public HttpResponseHeader Response => Document.ResponseHeader; #pragma warning restore CS0618 public void Dispose() diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs index 2120761..0b125f3 100644 --- a/MaxLib.WebServer/WebServerTaskCreator.cs +++ b/MaxLib.WebServer/WebServerTaskCreator.cs @@ -15,7 +15,6 @@ public WebServerTaskCreator() Task = new WebProgressTask() { CurrentStage = ServerStage.FIRST_STAGE, - Document = new HttpDocument(), Connection = new HttpConnection { Ip = "127.0.0.1", From 7d0d871b8e0358c541bd29ee77cdbcb25fb39c73 Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 16:53:18 +0100 Subject: [PATCH 3/7] remove unsued HttpConnection fields --- MaxLib.WebServer/HttpConnection.cs | 8 -------- MaxLib.WebServer/HttpDocument.cs | 12 +++++++----- MaxLib.WebServer/WebServerTaskCreator.cs | 1 - 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/MaxLib.WebServer/HttpConnection.cs b/MaxLib.WebServer/HttpConnection.cs index 18d3a4c..c258960 100644 --- a/MaxLib.WebServer/HttpConnection.cs +++ b/MaxLib.WebServer/HttpConnection.cs @@ -8,8 +8,6 @@ namespace MaxLib.WebServer [Serializable] public class HttpConnection { - public byte[] ConnectionKey { get; set; } - public string Ip { get; set; } public TcpClient NetworkClient { get; set; } @@ -17,11 +15,5 @@ public class HttpConnection public Stream NetworkStream { get; set; } public int LastWorkTime { get; set; } - - public Dictionary SessionInformation { get; private set; } - = new Dictionary(); - - public void AlwaysSyncSessionInformation(Dictionary information) - => SessionInformation = information ?? throw new ArgumentNullException(nameof(information)); } } diff --git a/MaxLib.WebServer/HttpDocument.cs b/MaxLib.WebServer/HttpDocument.cs index ce22d83..e3e2a75 100644 --- a/MaxLib.WebServer/HttpDocument.cs +++ b/MaxLib.WebServer/HttpDocument.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -9,22 +11,22 @@ public class HttpDocument : IDisposable { public List DataSources { get; } = new List(); - public string PrimaryMime + public string? PrimaryMime { get { return DataSources.Count == 0 ? null : DataSources[0].MimeType; } } - public string PrimaryEncoding { get; set; } = null; + public string? PrimaryEncoding { get; set; } = null; [Obsolete("Use WebProgressTask.Request. this will be removed in a future release.")] public HttpRequestHeader RequestHeader { get; set; } = new HttpRequestHeader(); [Obsolete("Use WebProgressTask.Response. this will be removed in a future release.")] public HttpResponseHeader ResponseHeader { get; set; } = new HttpResponseHeader(); - - public Dictionary Information { get; } = new Dictionary(); - public object this[object identifer] + public Dictionary Information { get; } = new Dictionary(); + + public object? this[object? identifer] { get => Information[identifer]; set => Information[identifer] = value; diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs index 0b125f3..ffbf009 100644 --- a/MaxLib.WebServer/WebServerTaskCreator.cs +++ b/MaxLib.WebServer/WebServerTaskCreator.cs @@ -19,7 +19,6 @@ public WebServerTaskCreator() { Ip = "127.0.0.1", LastWorkTime = -1, - ConnectionKey = new byte[0], }, NetworkStream = new MemoryStream() }; From c96d187b3ac1f5dbc29bb0dcb4a27c8b53b872b3 Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 16:59:20 +0100 Subject: [PATCH 4/7] deprecate Server.CreateRandomConnection() --- MaxLib.WebServer/HttpConnection.cs | 10 ++++++---- MaxLib.WebServer/SSL/SecureWebServer.cs | 12 +++++++----- MaxLib.WebServer/Server.cs | 24 +++++++++-------------- MaxLib.WebServer/Testing/TestTask.cs | 2 +- MaxLib.WebServer/Testing/TestWebServer.cs | 1 + MaxLib.WebServer/WebServerTaskCreator.cs | 1 - 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/MaxLib.WebServer/HttpConnection.cs b/MaxLib.WebServer/HttpConnection.cs index c258960..78cb59a 100644 --- a/MaxLib.WebServer/HttpConnection.cs +++ b/MaxLib.WebServer/HttpConnection.cs @@ -3,17 +3,19 @@ using System.IO; using System.Net.Sockets; +#nullable enable + namespace MaxLib.WebServer { [Serializable] public class HttpConnection { - public string Ip { get; set; } + public string? Ip { get; set; } - public TcpClient NetworkClient { get; set; } + public TcpClient? NetworkClient { get; set; } - public Stream NetworkStream { get; set; } + public Stream? NetworkStream { get; set; } - public int LastWorkTime { get; set; } + public int LastWorkTime { get; set; } = -1; } } diff --git a/MaxLib.WebServer/SSL/SecureWebServer.cs b/MaxLib.WebServer/SSL/SecureWebServer.cs index 6ee8d42..11484f7 100644 --- a/MaxLib.WebServer/SSL/SecureWebServer.cs +++ b/MaxLib.WebServer/SSL/SecureWebServer.cs @@ -76,11 +76,13 @@ protected virtual void SecureClientConnected(TcpClient client) return; } //prepare session - var connection = CreateRandomConnection(); - connection.NetworkClient = client; - connection.Ip = client.Client.RemoteEndPoint is IPEndPoint iPEndPoint - ? iPEndPoint.Address.ToString() - : client.Client.RemoteEndPoint.ToString(); + var connection = new HttpConnection() + { + NetworkClient = client, + Ip = client.Client.RemoteEndPoint is IPEndPoint iPEndPoint + ? iPEndPoint.Address.ToString() + : client.Client.RemoteEndPoint.ToString(), + }; AllConnections.Add(connection); //listen to connection _ = Task.Run(async () => diff --git a/MaxLib.WebServer/Server.cs b/MaxLib.WebServer/Server.cs index 3e0681e..45a8bde 100644 --- a/MaxLib.WebServer/Server.cs +++ b/MaxLib.WebServer/Server.cs @@ -147,11 +147,13 @@ protected virtual void ServerMainTask() protected virtual void ClientConnected(TcpClient client) { //prepare session - var connection = CreateRandomConnection(); - connection.NetworkClient = client; - connection.Ip = client.Client.RemoteEndPoint is IPEndPoint iPEndPoint - ? iPEndPoint.Address.ToString() - : client.Client.RemoteEndPoint.ToString(); + var connection = new HttpConnection() + { + NetworkClient = client, + Ip = client.Client.RemoteEndPoint is IPEndPoint iPEndPoint + ? iPEndPoint.Address.ToString() + : client.Client.RemoteEndPoint.ToString(), + }; AllConnections.Add(connection); //listen to connection _ = Task.Run(async () => await SafeClientStartListen(connection)); @@ -250,18 +252,10 @@ protected virtual WebProgressTask PrepairProgressTask(HttpConnection connection) }; } + [Obsolete("this method is no longer used by the server")] protected virtual HttpConnection CreateRandomConnection() { - var s = new HttpConnection(); - var r = new Random(); - do - { - s.ConnectionKey = new byte[16]; - r.NextBytes(s.ConnectionKey); - } - while (AllConnections.Exists((ht) => ht != null && WebServerUtils.BytesEqual(ht.ConnectionKey, s.ConnectionKey))); - s.LastWorkTime = -1; - return s; + return new HttpConnection(); } } } diff --git a/MaxLib.WebServer/Testing/TestTask.cs b/MaxLib.WebServer/Testing/TestTask.cs index 921eba9..bc05567 100644 --- a/MaxLib.WebServer/Testing/TestTask.cs +++ b/MaxLib.WebServer/Testing/TestTask.cs @@ -40,7 +40,7 @@ public MemoryStream SetStream(string input, Encoding encoding) /// Generate a random session and assign it to the task /// public void SetConnection() - => SetConnection(WebServer.CreateRandomConnection()); + => SetConnection(new HttpConnection()); public void SetConnection(HttpConnection connection) { diff --git a/MaxLib.WebServer/Testing/TestWebServer.cs b/MaxLib.WebServer/Testing/TestWebServer.cs index 6e30e90..7387a96 100644 --- a/MaxLib.WebServer/Testing/TestWebServer.cs +++ b/MaxLib.WebServer/Testing/TestWebServer.cs @@ -56,6 +56,7 @@ public Task Execute(WebProgressTask task, ServerStage terminationState = ServerS public new void RemoveConnection(HttpConnection connection) => base.RemoveConnection(connection); + [Obsolete("This method is no longer internaly used")] public new HttpConnection CreateRandomConnection() => base.CreateRandomConnection(); diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs index ffbf009..dfd5cad 100644 --- a/MaxLib.WebServer/WebServerTaskCreator.cs +++ b/MaxLib.WebServer/WebServerTaskCreator.cs @@ -18,7 +18,6 @@ public WebServerTaskCreator() Connection = new HttpConnection { Ip = "127.0.0.1", - LastWorkTime = -1, }, NetworkStream = new MemoryStream() }; From 98b4cd7c0fdeebc47cb053dc8420ca5a3fbbf611 Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 17:38:19 +0100 Subject: [PATCH 5/7] add nullable flag --- MaxLib.WebServer/HttpCookie.cs | 4 ++- MaxLib.WebServer/HttpDataSource.cs | 5 ++- MaxLib.WebServer/HttpFileDataSource.cs | 14 ++++++--- MaxLib.WebServer/HttpHeader.cs | 26 ++++++++++++++- MaxLib.WebServer/HttpLocation.cs | 7 ++++- MaxLib.WebServer/HttpPost.cs | 10 +++--- MaxLib.WebServer/HttpProtocollDefinition.cs | 2 ++ MaxLib.WebServer/HttpRequestHeader.cs | 8 +++-- MaxLib.WebServer/HttpResponseHeader.cs | 26 ++++++++------- MaxLib.WebServer/HttpStreamDataSource.cs | 2 ++ MaxLib.WebServer/HttpStringDataSource.cs | 4 ++- MaxLib.WebServer/MimeType.cs | 2 ++ MaxLib.WebServer/MultipartRanges.cs | 10 +++--- MaxLib.WebServer/Server.cs | 35 +++++++++++++-------- MaxLib.WebServer/ServerLogAddedHandler.cs | 4 ++- MaxLib.WebServer/ServerLogArgs.cs | 2 ++ MaxLib.WebServer/ServerLogItem.cs | 2 ++ MaxLib.WebServer/WebServerLog.cs | 6 ++-- MaxLib.WebServer/WebServerSettings.cs | 7 +++-- MaxLib.WebServer/WebServerTaskCreator.cs | 4 ++- MaxLib.WebServer/WebServerUtils.cs | 2 ++ MaxLib.WebServer/WebService.cs | 4 ++- MaxLib.WebServer/WebServiceGroup.cs | 10 +++--- 23 files changed, 140 insertions(+), 56 deletions(-) diff --git a/MaxLib.WebServer/HttpCookie.cs b/MaxLib.WebServer/HttpCookie.cs index e194134..f9c9d12 100644 --- a/MaxLib.WebServer/HttpCookie.cs +++ b/MaxLib.WebServer/HttpCookie.cs @@ -3,6 +3,8 @@ using System.Collections.ObjectModel; using System.Text; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -68,7 +70,7 @@ public override string ToString() } } - public string CompleteRequestCookie { get; private set; } + public string CompleteRequestCookie { get; private set; } = ""; public Dictionary AddedCookies { get; } diff --git a/MaxLib.WebServer/HttpDataSource.cs b/MaxLib.WebServer/HttpDataSource.cs index 6229637..4ba5848 100644 --- a/MaxLib.WebServer/HttpDataSource.cs +++ b/MaxLib.WebServer/HttpDataSource.cs @@ -3,6 +3,8 @@ using System.IO; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -43,7 +45,8 @@ public async Task WriteStream(Stream stream, long start, long? stop) { _ = stream ?? throw new ArgumentNullException(nameof(stream)); if (start < 0) throw new ArgumentOutOfRangeException(nameof(start)); - if (Length() != null && start >= Length().Value) + var length = Length(); + if (length != null && start >= length.Value) throw new ArgumentOutOfRangeException(nameof(start)); if (stop != null && stop < start) throw new ArgumentOutOfRangeException(nameof(stop)); return await WriteStreamInternal(stream, start, stop); diff --git a/MaxLib.WebServer/HttpFileDataSource.cs b/MaxLib.WebServer/HttpFileDataSource.cs index cd9ca7c..0a56cdd 100644 --- a/MaxLib.WebServer/HttpFileDataSource.cs +++ b/MaxLib.WebServer/HttpFileDataSource.cs @@ -3,15 +3,17 @@ using System.IO; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { [Serializable] public class HttpFileDataSource : HttpDataSource { - public FileStream File { get; private set; } + public FileStream? File { get; private set; } - private string path = null; - public virtual string Path + private string? path = null; + public virtual string? Path { get => path; set @@ -37,7 +39,7 @@ public virtual string Path public override bool CanProvideData => true; - public HttpFileDataSource(string path, bool readOnly = true) + public HttpFileDataSource(string? path, bool readOnly = true) { ReadOnly = readOnly; Path = path; @@ -54,6 +56,8 @@ public override void Dispose() protected override async Task WriteStreamInternal(Stream stream, long start, long? stop) { await Task.CompletedTask; + if (File == null) + return 0; File.Position = start; using (var skip = new SkipableStream(File, 0)) { @@ -75,6 +79,8 @@ protected override async Task ReadStreamInternal(Stream stream, long? leng await Task.CompletedTask; if (ReadOnly) throw new NotSupportedException(); + if (File == null) + return 0; File.Position = 0; using (var skip = new SkipableStream(File, 0)) { diff --git a/MaxLib.WebServer/HttpHeader.cs b/MaxLib.WebServer/HttpHeader.cs index 045ffe9..10d5167 100644 --- a/MaxLib.WebServer/HttpHeader.cs +++ b/MaxLib.WebServer/HttpHeader.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -20,11 +22,33 @@ public string HttpProtocol public Dictionary HeaderParameter { get; } = new Dictionary(); - public void SetHeader(IEnumerable<(string, string)> headers) + public string? GetHeader(string key) + { + _ = key ?? throw new ArgumentNullException(nameof(key)); + return HeaderParameter.TryGetValue(key, out string value) ? value : null; + } + + public void SetHeader(IEnumerable<(string, string?)> headers) { _ = headers ?? throw new ArgumentNullException(nameof(headers)); foreach (var (key, value) in headers) + if (value != null) + HeaderParameter[key] = value; + else HeaderParameter.Remove(key); + } + + public void SetHeader(params (string, string?)[] header) + { + _ = header ?? throw new ArgumentNullException(nameof(header)); + SetHeader(headers: header); + } + + public void SetHeader(string key, string? value) + { + _ = key ?? throw new ArgumentNullException(nameof(key)); + if (value != null) HeaderParameter[key] = value; + else HeaderParameter.Remove(key); } private string protocolMethod = HttpProtocollMethod.Get; diff --git a/MaxLib.WebServer/HttpLocation.cs b/MaxLib.WebServer/HttpLocation.cs index 5580e7f..75db800 100644 --- a/MaxLib.WebServer/HttpLocation.cs +++ b/MaxLib.WebServer/HttpLocation.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Text.RegularExpressions; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -56,8 +58,11 @@ public virtual void SetLocation(string url) public HttpLocation(string url) { - _ = url ?? throw new ArgumentNullException(nameof(url)); + Url = url ?? throw new ArgumentNullException(nameof(url)); GetParameter = new Dictionary(); + DocumentPath = ""; + DocumentPathTiles = new string[0]; + CompleteGet = ""; SetLocation(url); } diff --git a/MaxLib.WebServer/HttpPost.cs b/MaxLib.WebServer/HttpPost.cs index 016d8f4..690c007 100644 --- a/MaxLib.WebServer/HttpPost.cs +++ b/MaxLib.WebServer/HttpPost.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Text.RegularExpressions; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -9,11 +11,11 @@ public class HttpPost { public string CompletePost { get; private set; } - public string MimeType { get; private set; } + public string? MimeType { get; private set; } public Dictionary PostParameter { get; } - public virtual void SetPost(string post, string mime) + public virtual void SetPost(string post, string? mime) { CompletePost = post ?? throw new ArgumentNullException("Post"); @@ -73,9 +75,9 @@ protected virtual void SetPostFormData(string post, string boundary) } - public HttpPost(string post, string mime) + public HttpPost(string post, string? mime) { - _ = post ?? throw new ArgumentNullException(nameof(post)); + CompletePost = post ?? throw new ArgumentNullException(nameof(post)); PostParameter = new Dictionary(); SetPost(post, mime); } diff --git a/MaxLib.WebServer/HttpProtocollDefinition.cs b/MaxLib.WebServer/HttpProtocollDefinition.cs index 7629416..8e8590d 100644 --- a/MaxLib.WebServer/HttpProtocollDefinition.cs +++ b/MaxLib.WebServer/HttpProtocollDefinition.cs @@ -1,6 +1,8 @@ using System; using System.Linq; +#nullable enable + namespace MaxLib.WebServer { public static class HttpProtocollDefinition diff --git a/MaxLib.WebServer/HttpRequestHeader.cs b/MaxLib.WebServer/HttpRequestHeader.cs index 17b2bc3..c5dd2a2 100644 --- a/MaxLib.WebServer/HttpRequestHeader.cs +++ b/MaxLib.WebServer/HttpRequestHeader.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -27,10 +29,10 @@ public string Host public HttpConnectionType FieldConnection { get; set; } = HttpConnectionType.Close; public HttpCookie Cookie { get; } = new HttpCookie(""); - public string FieldUserAgent + public string? FieldUserAgent { - get => HeaderParameter.TryGetValue("User-Agent", out string value) ? value : null; - set => HeaderParameter["User-Agent"] = value; + get => GetHeader("User-Agent"); + set => SetHeader("User-Agent", value); } } } diff --git a/MaxLib.WebServer/HttpResponseHeader.cs b/MaxLib.WebServer/HttpResponseHeader.cs index f73d31e..75d99f7 100644 --- a/MaxLib.WebServer/HttpResponseHeader.cs +++ b/MaxLib.WebServer/HttpResponseHeader.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -7,28 +9,28 @@ public class HttpResponseHeader : HttpHeader { public HttpStateCode StatusCode { get; set; } = HttpStateCode.OK; - public string FieldLocation + public string? FieldLocation { - get => HeaderParameter.TryGetValue("Location", out string value) ? value : null; - set => HeaderParameter["Location"] = value; + get => GetHeader("Location"); + set => SetHeader("Location", value); } - public string FieldDate + public string? FieldDate { - get => HeaderParameter.TryGetValue("Date", out string value) ? value : null; - set => HeaderParameter["Date"] = value; + get => GetHeader("Date"); + set => SetHeader("Date", value); } - public string FieldLastModified + public string? FieldLastModified { - get => HeaderParameter.TryGetValue("Last-Modified", out string value) ? value : null; - set => HeaderParameter["Last-Modified"] = value; + get => GetHeader("Last-Modified"); + set => SetHeader("Last-Modified", value); } - public string FieldContentType + public string? FieldContentType { - get => HeaderParameter.TryGetValue("Content-Type", out string value) ? value : null; - set => HeaderParameter["Content-Type"] = value; + get => GetHeader("Content-Type"); + set => SetHeader("Content-Type", value); } public virtual void SetActualDate() diff --git a/MaxLib.WebServer/HttpStreamDataSource.cs b/MaxLib.WebServer/HttpStreamDataSource.cs index ec2ddb7..6e3ae7a 100644 --- a/MaxLib.WebServer/HttpStreamDataSource.cs +++ b/MaxLib.WebServer/HttpStreamDataSource.cs @@ -3,6 +3,8 @@ using System.IO; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { [Serializable] diff --git a/MaxLib.WebServer/HttpStringDataSource.cs b/MaxLib.WebServer/HttpStringDataSource.cs index 635cdad..b72491b 100644 --- a/MaxLib.WebServer/HttpStringDataSource.cs +++ b/MaxLib.WebServer/HttpStringDataSource.cs @@ -4,6 +4,8 @@ using System.Text; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -22,7 +24,7 @@ public string TextEncoding get => encoding; set { - encoding = value; + encoding = value ?? throw new ArgumentNullException(nameof(value)); Encoder = Encoding.GetEncoding(value); } } diff --git a/MaxLib.WebServer/MimeType.cs b/MaxLib.WebServer/MimeType.cs index 6653055..16e2dee 100644 --- a/MaxLib.WebServer/MimeType.cs +++ b/MaxLib.WebServer/MimeType.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace MaxLib.WebServer { /// diff --git a/MaxLib.WebServer/MultipartRanges.cs b/MaxLib.WebServer/MultipartRanges.cs index f132f13..4d4643d 100644 --- a/MaxLib.WebServer/MultipartRanges.cs +++ b/MaxLib.WebServer/MultipartRanges.cs @@ -5,6 +5,8 @@ using System.Text; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { [Serializable] @@ -55,13 +57,13 @@ public string ToString(long total) List ranges = new List(); [Obsolete("Use MultipartRanges(Stream, HttpRequestHeader, HttpResponseHeader, string) instead. This will be removed in a future release.")] - public MultipartRanges(Stream stream, HttpDocument document, string mime) + public MultipartRanges(Stream stream, HttpDocument document, string? mime) : this(stream, document.RequestHeader, document.ResponseHeader, mime) { } - public MultipartRanges(Stream stream, WebProgressTask task, string mime) + public MultipartRanges(Stream stream, WebProgressTask task, string? mime) : this( stream, task?.Request ?? throw new ArgumentNullException(nameof(task.Request)), @@ -73,12 +75,12 @@ public MultipartRanges(Stream stream, WebProgressTask task, string mime) } public MultipartRanges(Stream stream, HttpRequestHeader request, - HttpResponseHeader response, string mime) + HttpResponseHeader response, string? mime) { _ = request ?? throw new ArgumentNullException(nameof(request)); this.response = response ?? throw new ArgumentNullException(nameof(response)); baseStream = stream ?? throw new ArgumentNullException(nameof(stream)); - MimeType = mime; + MimeType = string.IsNullOrWhiteSpace(mime) ? WebServer.MimeType.TextHtml : mime; response.HeaderParameter["Accept-Ranges"] = "bytes"; if (request.HeaderParameter.ContainsKey("Range")) diff --git a/MaxLib.WebServer/Server.cs b/MaxLib.WebServer/Server.cs index 45a8bde..660bd87 100644 --- a/MaxLib.WebServer/Server.cs +++ b/MaxLib.WebServer/Server.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; //Source: Wikipedia, SelfHTML +#nullable enable namespace MaxLib.WebServer { @@ -18,8 +19,8 @@ public class Server //Serveraktivitäten - protected TcpListener Listener; - protected Thread ServerThread; + protected TcpListener? Listener; + protected Thread? ServerThread; public bool ServerExecution { get; protected set; } public SyncedList KeepAliveConnections { get; } = new SyncedList(); public SyncedList AllConnections { get; } = new SyncedList(); @@ -86,11 +87,13 @@ public virtual void Stop() { WebServerLog.Add(ServerLogType.Information, GetType(), "StartUp", "Stopped Server"); ServerExecution = false; - ServerThread.Join(); + ServerThread?.Join(); } protected virtual void ServerMainTask() { + if (Listener == null) + return; WebServerLog.Add(ServerLogType.Information, GetType(), "StartUp", "Server succesfuly started"); var watch = new Stopwatch(); while (ServerExecution) @@ -110,12 +113,16 @@ protected virtual void ServerMainTask() HttpConnection kas; try { kas = KeepAliveConnections[i]; } catch { continue; } - if (kas == null) continue; + if (kas == null) + continue; - if (!kas.NetworkClient.Connected || (kas.LastWorkTime != -1 && - kas.LastWorkTime + Settings.ConnectionTimeout < Environment.TickCount)) + if ((kas.NetworkClient != null && !kas.NetworkClient.Connected) || + (kas.LastWorkTime != -1 && + kas.LastWorkTime + Settings.ConnectionTimeout < Environment.TickCount + ) + ) { - kas.NetworkClient.Close(); + kas.NetworkClient?.Close(); kas.NetworkStream?.Dispose(); AllConnections.Remove(kas); KeepAliveConnections.Remove(kas); @@ -123,7 +130,9 @@ protected virtual void ServerMainTask() continue; } - if (kas.NetworkClient.Available > 0 && kas.LastWorkTime != -1) + if (kas.NetworkClient != null && kas.NetworkClient.Available > 0 && + kas.LastWorkTime != -1 + ) { _ = Task.Run(() => SafeClientStartListen(kas)); } @@ -138,7 +147,7 @@ protected virtual void ServerMainTask() watch.Stop(); Listener.Stop(); for (int i = 0; i < AllConnections.Count; ++i) - AllConnections[i].NetworkClient.Close(); + AllConnections[i].NetworkClient?.Close(); AllConnections.Clear(); KeepAliveConnections.Clear(); WebServerLog.Add(ServerLogType.Information, GetType(), "StartUp", "Server succesfuly stopped"); @@ -180,7 +189,7 @@ protected virtual async Task SafeClientStartListen(HttpConnection connection) protected virtual async Task ClientStartListen(HttpConnection connection) { connection.LastWorkTime = -1; - if (connection.NetworkClient.Connected) + if (connection.NetworkClient != null && connection.NetworkClient.Connected) { WebServerLog.Add(ServerLogType.Information, GetType(), "Connection", "Listen to Connection {0}", connection.NetworkClient.Client.RemoteEndPoint); @@ -214,7 +223,7 @@ protected void RemoveConnection(HttpConnection connection) if (KeepAliveConnections.Contains(connection)) KeepAliveConnections.Remove(connection); AllConnections.Remove(connection); - connection.NetworkClient.Close(); + connection.NetworkClient?.Close(); } internal protected virtual async Task ExecuteTaskChain(WebProgressTask task, ServerStage terminationState = ServerStage.FINAL_STAGE) @@ -232,13 +241,13 @@ internal protected virtual async Task ExecuteTaskChain(WebProgressTask task, Ser } } - protected virtual WebProgressTask PrepairProgressTask(HttpConnection connection) + protected virtual WebProgressTask? PrepairProgressTask(HttpConnection connection) { var stream = connection.NetworkStream; if (stream == null) try { - stream = connection.NetworkStream = connection.NetworkClient.GetStream(); + stream = connection.NetworkStream = connection.NetworkClient?.GetStream(); } catch (InvalidOperationException) { return null; } diff --git a/MaxLib.WebServer/ServerLogAddedHandler.cs b/MaxLib.WebServer/ServerLogAddedHandler.cs index e6a4ca2..6ceb744 100644 --- a/MaxLib.WebServer/ServerLogAddedHandler.cs +++ b/MaxLib.WebServer/ServerLogAddedHandler.cs @@ -1,4 +1,6 @@ -namespace MaxLib.WebServer +#nullable enable + +namespace MaxLib.WebServer { public delegate void ServerLogAddedHandler(ServerLogArgs eventArgs); } diff --git a/MaxLib.WebServer/ServerLogArgs.cs b/MaxLib.WebServer/ServerLogArgs.cs index 43e86e9..a94a67a 100644 --- a/MaxLib.WebServer/ServerLogArgs.cs +++ b/MaxLib.WebServer/ServerLogArgs.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace MaxLib.WebServer { public class ServerLogArgs : EventArgs diff --git a/MaxLib.WebServer/ServerLogItem.cs b/MaxLib.WebServer/ServerLogItem.cs index abfaaf6..d12921d 100644 --- a/MaxLib.WebServer/ServerLogItem.cs +++ b/MaxLib.WebServer/ServerLogItem.cs @@ -1,5 +1,7 @@ using System; +#nullable enable + namespace MaxLib.WebServer { [Serializable] diff --git a/MaxLib.WebServer/WebServerLog.cs b/MaxLib.WebServer/WebServerLog.cs index b64df7c..29cc491 100644 --- a/MaxLib.WebServer/WebServerLog.cs +++ b/MaxLib.WebServer/WebServerLog.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +#nullable enable + namespace MaxLib.WebServer { public static class WebServerLog @@ -11,12 +13,12 @@ public static class WebServerLog /// /// This event fires if some log item should be added. The log item can now filtered and discarded. /// - public static event ServerLogAddedHandler LogPreAdded; + public static event ServerLogAddedHandler? LogPreAdded; /// /// This event fires after a log item is added. /// - public static event Action LogAdded; + public static event Action? LogAdded; static readonly object lockObjekt = new object(); public static void Add(ServerLogItem logItem) diff --git a/MaxLib.WebServer/WebServerSettings.cs b/MaxLib.WebServer/WebServerSettings.cs index 68e2757..783cc14 100644 --- a/MaxLib.WebServer/WebServerSettings.cs +++ b/MaxLib.WebServer/WebServerSettings.cs @@ -4,6 +4,8 @@ using System.IO; using System.Net; +#nullable enable + namespace MaxLib.WebServer { public class WebServerSettings @@ -23,7 +25,8 @@ public IPAddress IPFilter public bool Debug_WriteRequests = false; public bool Debug_LogConnections = false; - public Dictionary DefaultFileMimeAssociation { get; } = new Dictionary(); + public Dictionary DefaultFileMimeAssociation { get; } + = new Dictionary(); protected enum SettingTypes { @@ -31,7 +34,7 @@ protected enum SettingTypes ServerSettings } - public string SettingsPath { get; private set; } + public string? SettingsPath { get; private set; } public virtual void LoadSettingFromData(string data) { diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs index dfd5cad..0d5a045 100644 --- a/MaxLib.WebServer/WebServerTaskCreator.cs +++ b/MaxLib.WebServer/WebServerTaskCreator.cs @@ -2,6 +2,8 @@ using System.IO; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { public class WebServerTaskCreator @@ -50,7 +52,7 @@ public void SetPost(string post, string mime) Task.Request.Post.SetPost(post, mime); } - public void SetAccept(string[] acceptTypes = null, string[] encoding = null) + public void SetAccept(string[]? acceptTypes = null, string[]? encoding = null) { if (acceptTypes != null) Task.Request.FieldAccept.AddRange(acceptTypes); if (encoding != null) Task.Request.FieldAcceptEncoding.AddRange(acceptTypes); diff --git a/MaxLib.WebServer/WebServerUtils.cs b/MaxLib.WebServer/WebServerUtils.cs index cf68612..c7e1560 100644 --- a/MaxLib.WebServer/WebServerUtils.cs +++ b/MaxLib.WebServer/WebServerUtils.cs @@ -2,6 +2,8 @@ using System.Globalization; using System.Net; +#nullable enable + namespace MaxLib.WebServer { public static class WebServerUtils diff --git a/MaxLib.WebServer/WebService.cs b/MaxLib.WebServer/WebService.cs index 56e9fcc..52a3994 100644 --- a/MaxLib.WebServer/WebService.cs +++ b/MaxLib.WebServer/WebService.cs @@ -1,6 +1,8 @@ using System; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { public abstract class WebService @@ -17,7 +19,7 @@ public WebService(ServerStage stage) public abstract bool CanWorkWith(WebProgressTask task); - public event EventHandler ImportanceChanged; + public event EventHandler? ImportanceChanged; WebProgressImportance importance; public WebProgressImportance Importance diff --git a/MaxLib.WebServer/WebServiceGroup.cs b/MaxLib.WebServer/WebServiceGroup.cs index 0c2fda3..d11f3a5 100644 --- a/MaxLib.WebServer/WebServiceGroup.cs +++ b/MaxLib.WebServer/WebServiceGroup.cs @@ -2,6 +2,8 @@ using System; using System.Threading.Tasks; +#nullable enable + namespace MaxLib.WebServer { public class WebServiceGroup @@ -45,7 +47,7 @@ public void Add(WebService service) private void Service_ImportanceChanged(object sender, EventArgs e) { - var service = sender as WebService; + var service = (WebService)sender; Services.ChangePriority(service.Importance, service); } @@ -71,7 +73,7 @@ public bool Contains(WebService service) public T Get() where T : WebService { - return Services.Find((ws) => ws is T) as T; + return (T)Services.Find((ws) => ws is T); } public virtual async Task Execute(WebProgressTask task) @@ -81,10 +83,10 @@ public virtual async Task Execute(WebProgressTask task) var services = Services.ToArray(); foreach (var service in services) { - if (task.Connection.NetworkClient != null && !task.Connection.NetworkClient.Connected) return; + if (task.Connection?.NetworkClient != null && !task.Connection.NetworkClient.Connected) return; if (service.CanWorkWith(task)) { - if (task.Connection.NetworkClient != null && !task.Connection.NetworkClient.Connected) return; + if (task.Connection?.NetworkClient != null && !task.Connection.NetworkClient.Connected) return; await service.ProgressTask(task); task.Document[Stage] = true; if (se) From 46e11a2b3b2fac8cb2227b61f4c33f7c23dc84be Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 19:01:50 +0100 Subject: [PATCH 6/7] add readme --- README.md | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 189 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7403250..55357da 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,190 @@ # MaxLib.WebServer -A full web server written in C# + +[![.NET Core](https://github.com/Garados007/MaxLib.WebServer/workflows/.NET%20Core/badge.svg?branch=main)](https://github.com/Garados007/MaxLib.WebServer/actions?query=workflow%3A%22.NET+Core%22) +[![NuGet Publish](https://github.com/Garados007/MaxLib.WebServer/workflows/NuGet%20Publish/badge.svg)](https://www.nuget.org/packages?q=Garados007+MaxLib.WebServer) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/Garados007/MaxLib.WebServer/blob/master/LICENSE) +[![Current Version](https://img.shields.io/github/tag/garados007/MaxLib.WebServer.svg?label=release)](https://github.com/Garados007/MaxLib.WebServer/releases) +![Top Language](https://img.shields.io/github/languages/top/garados007/MaxLib.WebServer.svg) + +`MaxLib.WebServer` is a full web server written in C#. To use this webserver you only need to add the .NuGet package to your project, instantiate the server in your code and thats it. No special configuration files or multiple processes. + +This web server is build modular. Any modules can be replaced by you and you decide what the server is cabable of. The server can fully configured (including exchanging the modules) during runtime - no need to restart everything. + +Some of the current features of the web server are: +- HTTP web server (of course, that's the purpose of the project) +- HTTPS web server with SSL certificates +- HTTP and HTTPS web server on the same port. The server detects automaticly what the user intends to use. +- Asynchronous handling of requests. Every part of the pipeline works with awaitable Tasks. +- REST Api builder. You can directly bind your methods to the handlers. +- Chunked transport. The server understands chunked datastreams and can produce these. +- Lazy handling of requests. The server allows you to produce the content while you are sending the response. No need to wait. +- Work with components that belongs to another AppDomain with Marshaling. +- Deliver contents from your local drive (e.g. HDD) +- Session keeping. You can identify the user later. +- ... + +## Getting Started + +This will add MaxLib.WebServer to your project and create a basic server with basic functions. + +### Installing + +Add the `MaxLib.WebServer` package. + +```sh +dotnet add package MaxLib.WebServer +``` + +### Create a simple server + +Write somewhere in your code (e.g.) in your Main method of your programm the following snippet: + +```csharp +using MaxLib.WebServer; +using MaxLib.WebServer.Services; + +// in your code +void SetupServer() +{ + // this expects that server is a variable that you have defined in your class + server = new Server(new WebServerSettings( + 8000, // this will run the server on port 8000 + 5000 // set the timout to 5 seconds. + )); + + // now add some services. You can use your own implementations but here we + // will add a basic set of services from MaxLib.WebServer.Services. + + // this will read the request from the network stream + server.AddWebService(new HttpHeaderParser()); + // this will read the header information and prepare them for later usage. + server.AddWebService(new HttpHeaderPostParser()); + // this will take care of HTTP OPTIONS or HEAD requests + server.AddWebService(new HttpHeaderSpecialAction()); + // this will serve 404 responses if no service has created a content for the request + server.AddWebService(new Http404Service()); + // this will prepare the response headers before everything will be send to the user + server.AddWebService(new HttpResponseCreator()); + // this will send the response to the user + server.AddWebService(new HttpSender()); + + // the server can now be startet. A basic set of services is defined so a new + // request will be handled and the user gets a response. Right now its a + // 404 NOT FOUND but we will add more. + server.Start(); + + // if you don't need the server anymore you can close the server with + server.Stop(); +} + +``` + +Right now you can start the server and open the url [http://localhost:8000](http://localhost:8000) in your browser and will get a nice 404 response. + +### Create own service + +Now we will create our own service, that will responds with a beatiful "Hello World" message. + +Create a new class `HelloWorldService` and put this code in it: + +```csharp +using System; +using System.Threading.Tasks; +using MaxLib.WebServer; +using MaxLib.WebServer.Services; + +// every service needs to be derived from WebService +public class HelloWorldService : WebService +{ + public HelloWorldService() + // This will tell the server when this service should be executed. + : base(ServerStage.CreateDocument) + { + // This tells the priority this service will be executed in the current stage. + // right now we want the default normal priority. + Importance = WebProgressImportance.Normal; // optional + } + + // the server asks every service in the current stage if they can do something + // with the current request. Right now we only want to act if the url is + // "/hello". This needs to be checked here. + public override bool CanWorkWith(WebProgressTask task) + { + // IsUrl checks if the path is "/hello" or "/hello/". + return task.Request.Location.IsUrl(new[] { "hello" }); + // If you want to check for "/hello/world" you need to call: + // return task.Request.Location.IsUrl(new[] { "hello", "world" }); + } + + // this function will be called from the server only if CanWorkWith succeeds. + // Here we create our response + public override async Task ProgressTask(WebProgressTask task) + { + // Our response. In this case a simple html page. + var text = "Hello World" + + "

    Hello World!

    "; + // now we add the result to the output. We can add any kind of data + // source. This library has the helper classes for strings, Streams + // and files. + task.Document.DataSources.Add(new HttpStringDataSource(text) + { + // this will specify the Mime-Type as "text/html". The static + // class MimeType contains many definitions but you can use your + // own here if you want. The default Mime-Type is "text/plain". + MimeType = MimeType.TextHtml, + // you can specify your encoding here. Default is "utf-8". + TextEncoding = "utf-8", + }); + // we are now finished + await Task.CompletedTask; + } +} +``` + +Now you need to add this line to add your service to server: + +```csharp +server.AddWebService(new HelloWorldService()); +``` + +After that you can run your programm and open the page [http://localhost:8000/hello](http://localhost:8000/hello). You will see your hello world message. + +## Example + +- [example/MaxLib.WebServer.Example](example/MaxLib.WebServer.Example) + - create a basic webserver + +## Contributing + +Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. + +## Versioning + +We use [SemVer](semver.org) for versioning. For the versions available, see the [tags on this repository](https://github.com/Garados007/MaxLib.WebServer/tags). + +## Authors + +- **Max Brauer** - *Initial work* - [Garados007](https://github.com/Garados007) + +See also the list of [contributors](https://github.com/Garados007/srpc/contributors) who participated in this project. + +## Lincense + +This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details + +## Acknowledgments + +- StackOverflow for the help +- Wikipedia, SelfHTML and Mozilla for their documentation +- [PurpleBooth](https://github.com/PurpleBooth) for her [README.md](https://gist.github.com/PurpleBooth/109311bb0361f32d87a2) template + +## Last Words + +This project was a free time project of mine and I have done it because why not. The source +code was a long time a part of [MaxLib](https://github.com/Garados007/MaxLib) (a collection +of other fun projects and code) but got its own repository for better maintenance. + +Some of the documentation inside the code is still in German and other things needs to be +optimized. + +I have used this for some projects with my friends. It can handle some TB of traffic over a long period without any problems or crashes. I am a little proud of this. From 1b8ac0cf25b72ff877b424b18b5077991fa5afa9 Mon Sep 17 00:00:00 2001 From: Max Brauer Date: Fri, 18 Dec 2020 19:02:47 +0100 Subject: [PATCH 7/7] move version from 2.0.0 to 2.1.0 --- MaxLib.WebServer/MaxLib.WebServer.csproj.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MaxLib.WebServer/MaxLib.WebServer.csproj.include b/MaxLib.WebServer/MaxLib.WebServer.csproj.include index fb8864b..f89408f 100644 --- a/MaxLib.WebServer/MaxLib.WebServer.csproj.include +++ b/MaxLib.WebServer/MaxLib.WebServer.csproj.include @@ -2,7 +2,7 @@ - 2.0.0 + 2.1.0 $(Version).0 $(Version).0