diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..f88d3e7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Default setting
+* auto
+
+# Do nothing
+*.sln -text
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 6413b38..57a69a5 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -17,8 +17,8 @@ jobs:
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
+ 8.0
6.0.102
- 3.1.101
- name: Install dependencies
run: dotnet restore
- name: Build
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
index 96ba277..b30ed37 100644
--- a/.github/workflows/nuget.yml
+++ b/.github/workflows/nuget.yml
@@ -10,17 +10,17 @@ jobs:
steps:
- uses: actions/checkout@v2
-
+
- name: Init git submodules
run: git submodule init && git submodule update
-
+
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 6.0.102
+ dotnet-version: '8.0'
- name: Install dependencies
run: dotnet restore
-
+
- name: Publish MaxLib.WebServer NuGet
uses: brandedoutcast/publish-nuget@v2.5.5
with:
diff --git a/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj b/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj
deleted file mode 100644
index 18e63ed..0000000
--- a/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
- netcoreapp3.1
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/MaxLib.WebServer.sln b/MaxLib.WebServer.sln
index d610ccd..4533fcc 100644
--- a/MaxLib.WebServer.sln
+++ b/MaxLib.WebServer.sln
@@ -5,13 +5,13 @@ VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer", "MaxLib.WebServer\MaxLib.WebServer.csproj", "{595DB1BF-246A-4A42-99EB-5DAB7709E21E}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer.Test", "MaxLib.WebServer.Test\MaxLib.WebServer.Test.csproj", "{60225D92-5742-4BC0-A3A5-206123F2129D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer.Test", "tests\MaxLib.WebServer.Test\MaxLib.WebServer.Test.csproj", "{60225D92-5742-4BC0-A3A5-206123F2129D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer.Example", "example\MaxLib.WebServer.Example\MaxLib.WebServer.Example.csproj", "{6616448A-1AD7-4897-9124-F1560FB12461}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Example", "Example", "{39740782-6F07-470C-92B8-C0A07A5C0DFB}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer.WebSocket.Echo", "MaxLib.WebServer.WebSocket.Echo\MaxLib.WebServer.WebSocket.Echo.csproj", "{01C302FF-8E99-4D54-8234-D4BA59862176}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaxLib.WebServer.WebSocket.Echo", "example\MaxLib.WebServer.WebSocket.Echo\MaxLib.WebServer.WebSocket.Echo.csproj", "{01C302FF-8E99-4D54-8234-D4BA59862176}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{29467014-E04B-477A-82B7-16A3BAE7B5A6}"
ProjectSection(SolutionItems) = preProject
diff --git a/MaxLib.WebServer/Api/ApiService.cs b/MaxLib.WebServer/Api/ApiService.cs
index 027dcb9..3c727fb 100644
--- a/MaxLib.WebServer/Api/ApiService.cs
+++ b/MaxLib.WebServer/Api/ApiService.cs
@@ -5,6 +5,7 @@
namespace MaxLib.WebServer.Api
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public abstract class ApiService : WebService
{
public ApiService(params string[] endpoint)
diff --git a/MaxLib.WebServer/Api/Rest/ApiGetRule.cs b/MaxLib.WebServer/Api/Rest/ApiGetRule.cs
index 2c933af..08ee9d4 100644
--- a/MaxLib.WebServer/Api/Rest/ApiGetRule.cs
+++ b/MaxLib.WebServer/Api/Rest/ApiGetRule.cs
@@ -4,6 +4,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public abstract class ApiGetRule : ApiRule
{
private string? key;
diff --git a/MaxLib.WebServer/Api/Rest/ApiLocationRule.cs b/MaxLib.WebServer/Api/Rest/ApiLocationRule.cs
index 19a99b4..55990e5 100644
--- a/MaxLib.WebServer/Api/Rest/ApiLocationRule.cs
+++ b/MaxLib.WebServer/Api/Rest/ApiLocationRule.cs
@@ -4,6 +4,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public abstract class ApiLocationRule : ApiRule
{
private int index = 0;
diff --git a/MaxLib.WebServer/Api/Rest/ApiRule.cs b/MaxLib.WebServer/Api/Rest/ApiRule.cs
index f89bd21..b10341d 100644
--- a/MaxLib.WebServer/Api/Rest/ApiRule.cs
+++ b/MaxLib.WebServer/Api/Rest/ApiRule.cs
@@ -1,7 +1,10 @@
#nullable enable
+using System;
+
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public abstract class ApiRule
{
public bool Required { get; set; } = true;
diff --git a/MaxLib.WebServer/Api/Rest/ApiRuleFactory.cs b/MaxLib.WebServer/Api/Rest/ApiRuleFactory.cs
index 83f4871..dff097e 100644
--- a/MaxLib.WebServer/Api/Rest/ApiRuleFactory.cs
+++ b/MaxLib.WebServer/Api/Rest/ApiRuleFactory.cs
@@ -6,6 +6,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public class ApiRuleFactory
{
public class HostRule : ApiRule
diff --git a/MaxLib.WebServer/Api/Rest/RestActionEndpoint.cs b/MaxLib.WebServer/Api/Rest/RestActionEndpoint.cs
index 268e6dc..c52e9a4 100644
--- a/MaxLib.WebServer/Api/Rest/RestActionEndpoint.cs
+++ b/MaxLib.WebServer/Api/Rest/RestActionEndpoint.cs
@@ -9,6 +9,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public class RestActionEndpoint : RestEndpoint
{
public Func, Task> HandleRequest { get; set; }
diff --git a/MaxLib.WebServer/Api/Rest/RestApiService.cs b/MaxLib.WebServer/Api/Rest/RestApiService.cs
index 870f56e..b4e5e98 100644
--- a/MaxLib.WebServer/Api/Rest/RestApiService.cs
+++ b/MaxLib.WebServer/Api/Rest/RestApiService.cs
@@ -6,6 +6,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public class RestApiService : ApiService
{
public List RestEndpoints { get; } = new List();
diff --git a/MaxLib.WebServer/Api/Rest/RestEndpoint.cs b/MaxLib.WebServer/Api/Rest/RestEndpoint.cs
index b6fd58f..d6d2d43 100644
--- a/MaxLib.WebServer/Api/Rest/RestEndpoint.cs
+++ b/MaxLib.WebServer/Api/Rest/RestEndpoint.cs
@@ -8,6 +8,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public class RestEndpoint
{
readonly private ApiRuleFactory.GroupRule rules = new ApiRuleFactory.GroupRule();
diff --git a/MaxLib.WebServer/Api/Rest/RestQueryArgs.cs b/MaxLib.WebServer/Api/Rest/RestQueryArgs.cs
index 306f21d..5755c38 100644
--- a/MaxLib.WebServer/Api/Rest/RestQueryArgs.cs
+++ b/MaxLib.WebServer/Api/Rest/RestQueryArgs.cs
@@ -5,6 +5,7 @@
namespace MaxLib.WebServer.Api.Rest
{
+ [Obsolete("The ApiService and the RestApiService classes are no longer maintained and will be removed in a future update. Use the Builder system instead.")]
public class RestQueryArgs
{
public string[] Location { get; }
diff --git a/MaxLib.WebServer/Chunked/HttpChunkedStream.cs b/MaxLib.WebServer/Chunked/HttpChunkedStream.cs
index b79581a..00daf83 100644
--- a/MaxLib.WebServer/Chunked/HttpChunkedStream.cs
+++ b/MaxLib.WebServer/Chunked/HttpChunkedStream.cs
@@ -23,11 +23,6 @@ public HttpChunkedStream(Stream baseStream, int readBufferLength = 0x8000)
public int ReadBufferLength { get; }
- [Obsolete]
- public override bool CanAcceptData => BaseStream.CanWrite;
-
- public override bool CanProvideData => BaseStream.CanRead;
-
public override long? Length() => null;
public override void Dispose()
@@ -35,41 +30,26 @@ public override void Dispose()
BaseStream.Dispose();
}
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
+ protected override async Task WriteStreamInternal(Stream stream)
{
long total = 0;
- int readed;
- byte[] buffer = new byte[ReadBufferLength];
- do
- {
- readed = await BaseStream.ReadAsync(
- buffer,
- 0,
- (int)Math.Min(buffer.Length, start - total)
- ).ConfigureAwait(false);
- total += readed;
- }
- while (total < start && readed > 0);
- if (readed == 0 && start > 0)
- return 0;
+ int read;
+ Memory buffer = new byte[ReadBufferLength];
var ascii = Encoding.ASCII;
- var nl = ascii.GetBytes("\r\n");
+ ReadOnlyMemory nl = ascii.GetBytes("\r\n");
do
{
- var read = stop == null
- ? buffer.Length
- : (int)Math.Min(buffer.Length, stop.Value - total);
- readed = await BaseStream.ReadAsync(buffer, 0, read).ConfigureAwait(false);
- if (readed <= 0)
- return total - start;
- var length = ascii.GetBytes(readed.ToString("X"));
+ read = await BaseStream.ReadAsync(buffer).ConfigureAwait(false);
+ if (read <= 0)
+ return total;
+ ReadOnlyMemory length = ascii.GetBytes(read.ToString("X"));
try
{
- await stream.WriteAsync(length, 0, length.Length).ConfigureAwait(false);
- await stream.WriteAsync(nl, 0, nl.Length).ConfigureAwait(false);
- await stream.WriteAsync(buffer, 0, readed).ConfigureAwait(false);
- await stream.WriteAsync(nl, 0, nl.Length).ConfigureAwait(false);
- total += readed;
+ await stream.WriteAsync(length).ConfigureAwait(false);
+ await stream.WriteAsync(nl).ConfigureAwait(false);
+ await stream.WriteAsync(buffer[0..read]).ConfigureAwait(false);
+ await stream.WriteAsync(nl).ConfigureAwait(false);
+ total += read;
await stream.FlushAsync().ConfigureAwait(false);
}
catch (IOException)
@@ -78,87 +58,8 @@ protected override async Task WriteStreamInternal(Stream stream, long star
return total;
}
}
- while (readed > 0);
- return total - start;
- }
-
- [Obsolete]
- protected override async Task ReadStreamInternal(Stream stream, long? length)
- {
- long total = 0;
- int readed, numberLength;
- var ascii = Encoding.ASCII;
- var buffer = new byte[0x10000];
- while (true)
- {
- try { numberLength = await ReadNumber(stream, buffer).ConfigureAwait(false); }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "read", "connection closed");
- return total;
- }
- if (numberLength == 0)
- return total;
- var numberString = ascii.GetString(buffer, 0, numberLength);
- if (!long.TryParse(numberString,
- NumberStyles.HexNumber,
- CultureInfo.InvariantCulture.NumberFormat,
- out long number) || number < 0)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "read", "invalid number of bytes indicator");
- return total;
- }
- while (number > 0)
- {
- try { readed = await stream.ReadAsync(buffer, 0, (int)Math.Min(number, buffer.Length)).ConfigureAwait(false); }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "read", "connection closed");
- return total;
- }
- if (readed == 0)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "read", "could not read the block completly");
- return total;
- }
- await BaseStream.WriteAsync(buffer, 0, readed).ConfigureAwait(false);
- total += readed;
- number -= readed;
- }
- try
- {
- readed = await stream.ReadAsync(buffer, 0, 1).ConfigureAwait(false);
- if (readed > 0 && buffer[0] == '\r')
- readed = await stream.ReadAsync(buffer, 0, 1).ConfigureAwait(false);
- if (readed == 0)
- return total;
- }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "read", "connection closed");
- return total;
- }
- }
- }
-
- private async Task ReadNumber(Stream stream, byte[] buffer)
- {
- int offset = 0;
- var byteBuffer = new byte[1];
- while (true)
- {
- int readed = await stream.ReadAsync(byteBuffer, 0, 1).ConfigureAwait(false);
- if (readed == 0)
- return offset;
- if (byteBuffer[0] == '\r' || byteBuffer[0] == '\n')
- {
- if (byteBuffer[0] == '\r')
- await stream.ReadAsync(byteBuffer, 0, 1).ConfigureAwait(false);
- return offset;
- }
- buffer[offset] = byteBuffer[0];
- offset++;
- }
+ while (read > 0);
+ return total;
}
}
}
diff --git a/MaxLib.WebServer/HttpDataSource.cs b/MaxLib.WebServer/HttpDataSource.cs
index 6698d52..e8c45b7 100644
--- a/MaxLib.WebServer/HttpDataSource.cs
+++ b/MaxLib.WebServer/HttpDataSource.cs
@@ -26,111 +26,18 @@ public virtual string MimeType
}
}
- [Obsolete("HttpDataSource become readonly in a future release")]
- public abstract bool CanAcceptData { get; }
-
- public abstract bool CanProvideData { get; }
-
- protected abstract Task WriteStreamInternal(Stream stream, long start, long? stop);
-
-
- [Obsolete("HttpDataSource become readonly in a future release")]
- protected abstract Task ReadStreamInternal(Stream stream, long? length);
+ protected abstract Task WriteStreamInternal(Stream stream);
///
- /// Write its content to .
- ///
- /// the stream to write the data into
- /// the first own byte (inclusive) that should have been written
- /// the last own byte (excklusive) that should have been written or null to write all bytes till the end
- /// the effective number of bytes written to the stream
- public async Task WriteStream(Stream stream, long start, long? stop)
- {
- _ = stream ?? throw new ArgumentNullException(nameof(stream));
- if (start < 0) throw new ArgumentOutOfRangeException(nameof(start));
- 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).ConfigureAwait(false);
- }
-
- ///
- /// Write its content to . It will start at
- /// (inclusive) and write until (exclusive). If
- /// is null it will write all bytes till the end.
+ /// Write the whole content to . If you want to have a partial
+ /// content use as a wrapper.
///
/// the stream to write the data into
/// the effective number of bytes written to the stream
public async Task WriteStream(Stream stream)
-#pragma warning disable CS0618
- => await WriteStream(stream ?? throw new ArgumentNullException(nameof(stream)), RangeStart, RangeEnd).ConfigureAwait(false);
-#pragma warning restore CS0618
-
- ///
- /// Read the data of and replace its own data with it.
- ///
- /// the stream to read the data from
- /// the number of bytes that should been readed. null to read all bytes.
- /// the number of bytes readed from the stream
- [Obsolete("HttpDataSource become readonly in a future release")]
- public async Task ReadStream(Stream stream, long? length = null)
{
_ = stream ?? throw new ArgumentNullException(nameof(stream));
- if (length != null && length < 0) throw new ArgumentOutOfRangeException(nameof(length));
- return await ReadStreamInternal(stream, length).ConfigureAwait(false);
- }
-
- private long rangeStart = 0;
- [Obsolete("HttpDataSource will change its Range behaviour")]
- public virtual long RangeStart
- {
- get => rangeStart;
- set
- {
- if (value < 0) throw new ArgumentOutOfRangeException(nameof(RangeStart));
- if (value > 0) TransferCompleteData = false;
- else if (rangeEnd == null) TransferCompleteData = true;
- rangeStart = value;
- }
- }
-
- private long? rangeEnd = null;
- [Obsolete("HttpDataSource will change its Range behaviour")]
- public virtual long? RangeEnd
- {
- get => rangeEnd;
- set
- {
- if (Length() == null && value != null)
- throw new ArgumentOutOfRangeException(nameof(RangeEnd));
- if (value != null && value < 0) throw new ArgumentOutOfRangeException(nameof(RangeEnd));
- if (value != null)
- TransferCompleteData = false;
- else if (rangeStart == 0)
- TransferCompleteData = true;
- rangeEnd = value;
- }
- }
-
- private bool transferCompleteData = true;
- [Obsolete("In a future release HttpDataSource will always transfer the complete data")]
- public virtual bool TransferCompleteData
- {
- get => transferCompleteData;
- set
- {
- if (transferCompleteData = value)
- {
- rangeStart = 0;
- rangeEnd = null;
- }
- else
- {
- if (rangeEnd == null)
- rangeEnd = Length();
- }
- }
+ return await WriteStreamInternal(stream).ConfigureAwait(false);
}
public static Stream TransformToStream(HttpDataSource dataSource)
diff --git a/MaxLib.WebServer/HttpException.cs b/MaxLib.WebServer/HttpException.cs
index 62e4f30..cea9a32 100644
--- a/MaxLib.WebServer/HttpException.cs
+++ b/MaxLib.WebServer/HttpException.cs
@@ -14,13 +14,13 @@ namespace MaxLib.WebServer
public class HttpException : System.Exception
{
public HttpException() { }
- public HttpException(string message) : base(message)
+ public HttpException(string message) : base(message)
{
DataSource = new HttpStringDataSource(message);
}
- public HttpException(string message, System.Exception inner) : base(message, inner)
- {
+ public HttpException(string message, System.Exception inner) : base(message, inner)
+ {
DataSource = new HttpStringDataSource(message);
}
@@ -40,12 +40,8 @@ public HttpException(HttpDataSource dataSource)
DataSource = dataSource;
}
- protected HttpException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
-
public HttpStateCode StateCode { get; set; } = HttpStateCode.InternalServerError;
public HttpDataSource? DataSource { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/MaxLib.WebServer/HttpFileDataSource.cs b/MaxLib.WebServer/HttpFileDataSource.cs
index 697392e..0db795b 100644
--- a/MaxLib.WebServer/HttpFileDataSource.cs
+++ b/MaxLib.WebServer/HttpFileDataSource.cs
@@ -1,113 +1,29 @@
-using MaxLib.IO;
-using System;
+using System;
using System.IO;
-using System.Threading.Tasks;
#nullable enable
namespace MaxLib.WebServer
{
[Serializable]
- public class HttpFileDataSource : HttpDataSource
+ public class HttpFileDataSource : HttpStreamDataSource
{
- public FileStream? File { get; private set; }
+ public FileStream File => (FileStream)Stream;
- private string? path = null;
- public virtual string? Path
- {
- get => path;
- set
- {
- if (path == value) return;
- if (File != null) File.Dispose();
- if (value == null) File = null;
- else
- {
- var fi = new FileInfo(value);
- if (!fi.Directory!.Exists) fi.Directory.Create();
- File = new FileStream(value, FileMode.OpenOrCreate,
-#pragma warning disable CS0612
- ReadOnly ? FileAccess.Read : FileAccess.ReadWrite,
-#pragma warning restore CS0612
- FileShare.ReadWrite);
- }
- path = value;
- }
- }
-
- [Obsolete]
- public bool ReadOnly { get; }
-
- [Obsolete]
- public override bool CanAcceptData => !ReadOnly;
-
- public override bool CanProvideData => true;
-
- public HttpFileDataSource(string? path)
- {
- Path = path;
- }
+ public string Path { get; }
- [Obsolete]
- public HttpFileDataSource(string? path, bool readOnly = true)
+ public HttpFileDataSource(string path)
+ : base(GetStream(path))
{
- ReadOnly = readOnly;
Path = path;
}
- public override void Dispose()
- {
- Path = null;
- }
-
- public override long? Length()
- => File?.Length;
-
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
- {
- await Task.CompletedTask.ConfigureAwait(false);
- if (File == null)
- return 0;
- File.Position = start;
- using (var skip = new SkipableStream(File, 0))
- {
- try
- {
- return skip.WriteToStream(stream,
- stop == null ? null : (long?)(stop.Value - start));
- }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
- return File.Position - start;
- }
- }
- }
-
- [Obsolete]
- protected override async Task ReadStreamInternal(Stream stream, long? length)
+ private static FileStream GetStream(string path)
{
- await Task.CompletedTask.ConfigureAwait(false);
- if (ReadOnly)
- throw new NotSupportedException();
- if (File == null)
- return 0;
- File.Position = 0;
- using (var skip = new SkipableStream(File, 0))
- {
- long readed;
- try
- {
- readed = skip.ReadFromStream(stream, length);
- }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
- readed = File.Position;
- }
- File.SetLength(readed);
- return readed;
- }
+ _ = path ?? throw new ArgumentNullException(nameof(path));
+ if (!System.IO.File.Exists(path))
+ throw new FileNotFoundException("required file not found", path);
+ return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
}
}
diff --git a/MaxLib.WebServer/HttpHeader.cs b/MaxLib.WebServer/HttpHeader.cs
index 4f209da..f6e9507 100644
--- a/MaxLib.WebServer/HttpHeader.cs
+++ b/MaxLib.WebServer/HttpHeader.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using MaxLib.Common.Collections;
#nullable enable
@@ -8,6 +9,35 @@ namespace MaxLib.WebServer
[Serializable]
public abstract class HttpHeader
{
+ private bool lockReset = false;
+
+ public HttpHeader()
+ {
+ var param = new ObservableDictionary(StringComparer.InvariantCultureIgnoreCase);
+ param.CollectionChanged += (_, __) =>
+ {
+ if (!lockReset)
+ ResetCache();
+ };
+ HeaderParameter = param;
+ }
+
+ ///
+ /// Set the current state of the reset lock. If the reset is locked all changes to
+ /// won't call and therefore
+ /// reset the cached state.
+ ///
+ /// the new state of the reset lock
+ protected internal void SetResetLock(bool lockReset)
+ {
+ this.lockReset = lockReset;
+ }
+
+ protected virtual void ResetCache()
+ {
+
+ }
+
private string httpProtocol = HttpProtocolDefinition.HttpVersion1_1;
public string HttpProtocol
{
@@ -20,8 +50,7 @@ public string HttpProtocol
}
}
- public Dictionary HeaderParameter { get; }
- = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ public ObservableDictionary HeaderParameter { get; }
public string? GetHeader(string key)
{
@@ -32,10 +61,13 @@ public string HttpProtocol
public void SetHeader(IEnumerable<(string, string?)> headers)
{
_ = headers ?? throw new ArgumentNullException(nameof(headers));
+ SetResetLock(true);
foreach (var (key, value) in headers)
if (value != null)
HeaderParameter[key] = value;
else HeaderParameter.Remove(key);
+ SetResetLock(false);
+ ResetCache();
}
public void SetHeader(params (string, string?)[] header)
diff --git a/MaxLib.WebServer/HttpPartialSource.cs b/MaxLib.WebServer/HttpPartialSource.cs
index 50bfbb8..01e1a8c 100644
--- a/MaxLib.WebServer/HttpPartialSource.cs
+++ b/MaxLib.WebServer/HttpPartialSource.cs
@@ -39,12 +39,20 @@ public HttpPartialSource(HttpDataSource dataSource, long start, long? count)
BaseSource = dataSource ?? throw new ArgumentNullException(nameof(dataSource));
Start = start;
Count = count;
- }
-
- [Obsolete]
- public override bool CanAcceptData => false;
- public override bool CanProvideData => true;
+ // optimize this constructor if you use nested partial sources
+ if (dataSource is HttpPartialSource partial)
+ {
+ BaseSource = partial.BaseSource;
+ Start += partial.Start;
+ if (Count != null && partial.Count != null)
+ Count = Math.Min(Count.Value, partial.Count.Value - Start);
+ else
+ {
+ Count ??= partial.Count - Start;
+ }
+ }
+ }
public override void Dispose()
{
@@ -59,74 +67,90 @@ public override void Dispose()
availableBaseLength == null ? Count : Math.Min(Count.Value, availableBaseLength.Value);
}
- [Obsolete]
- protected override Task ReadStreamInternal(Stream stream, long? length)
+ protected override async Task WriteStreamInternal(Stream stream)
{
- throw new NotSupportedException();
+ // optimize if stream based
+ if (BaseSource is HttpStreamDataSource streamDataSource)
+ {
+ var window = new StreamWindow(stream, 0, Count);
+ return await streamDataSource.WriteStream(window, Start, Count);
+ }
+ else
+ {
+ var window = new StreamWindow(stream, Start, Count);
+ return await BaseSource.WriteStream(window);
+ }
}
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
+ private class StreamWindow : Stream
{
- // start and stop will further restrict the limitations of this implementation.
- // In a future release this method will be simplified.
-
- var firstOutputByte = Start + start;
- var clientWindow = stop - start;
- var localWindow = Count - start;
- var window = localWindow == null ? clientWindow :
- clientWindow == null ? localWindow : Math.Min(localWindow.Value, clientWindow.Value);
-
- // throw first bytes away
- using var bin = new StreamBin();
- long total = await BaseSource.WriteStream(bin, 0, firstOutputByte)
- .ConfigureAwait(false);
- if (total < firstOutputByte)
- return 0;
-
- // read the rest of the source. This depends if the BaseSource is something we can seek
- // on. A future release will make the start-stop sequence obsolete therefore we no
- // longer need these special checks.
- if (BaseSource is HttpStreamDataSource sds && !sds.Stream.CanSeek)
- total = await BaseSource.WriteStream(stream, 0, window)
- .ConfigureAwait(false);
- else total = await BaseSource.WriteStream(stream, firstOutputByte, firstOutputByte + window);
-
- // we are finished with reading the data
- return total;
- }
+ public Stream Target { get; }
- private class StreamBin : Stream
- {
- public override bool CanRead => true;
+ public long Start { get; private set; }
+
+ public long? Count { get; private set; }
- public override bool CanSeek => true;
+ public StreamWindow(Stream target, long start, long? count)
+ {
+ Target = target;
+ Start = start;
+ Count = count;
+ }
+
+ public override bool CanRead => false;
+
+ public override bool CanSeek => false;
public override bool CanWrite => true;
- public override long Length => 0;
+ public override long Length => throw new NotSupportedException();
- public override long Position { get => 0; set {} }
+ public override long Position
+ {
+ get => throw new NotSupportedException();
+ set => throw new NotSupportedException();
+ }
public override void Flush()
{
+ Target.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
- return 0;
+ throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
- return 0;
+ throw new NotSupportedException();
}
public override void SetLength(long value)
{
+ throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
+ // skip bytes if available
+ if (Start > 0)
+ {
+ var skip = (int)Math.Min(Start, count);
+ Start -= skip;
+ offset += skip;
+ count -= skip;
+ }
+ // trim count if necessary
+ if (Start == 0 && Count != null)
+ {
+ var usable = (int)Math.Min(Count.Value, count);
+ count = usable;
+ Count = Count.Value - usable;
+ }
+ // perform write operation
+ if (count > 0)
+ Target.Write(buffer, offset, count);
}
}
}
diff --git a/MaxLib.WebServer/HttpRequestHeader.cs b/MaxLib.WebServer/HttpRequestHeader.cs
index 21e8475..a0bcc31 100644
--- a/MaxLib.WebServer/HttpRequestHeader.cs
+++ b/MaxLib.WebServer/HttpRequestHeader.cs
@@ -1,5 +1,5 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System;
#nullable enable
@@ -8,6 +8,17 @@ namespace MaxLib.WebServer
[Serializable]
public class HttpRequestHeader : HttpHeader
{
+ protected override void ResetCache()
+ {
+ base.ResetCache();
+ fieldAccept = null;
+ fieldAcceptCharset = null;
+ fieldAcceptEncoding = null;
+ fieldConnection = null;
+ host = null;
+ cookie = null;
+ }
+
public string Url
{
get => Location.Url;
@@ -16,23 +27,172 @@ public string Url
public HttpLocation Location { get; } = new HttpLocation("/");
- private string host = "";
+ private Lazy? host = null;
public string Host
{
- get => host;
- set => host = value ?? throw new ArgumentNullException(nameof(Host));
+ get
+ {
+ if (host != null)
+ return host.Value;
+ return (host = new Lazy(
+ () => HeaderParameter.TryGetValue("Host", out string value) ?
+ value : ""
+ )).Value;
+ }
+ set
+ {
+ _ = host ?? throw new ArgumentNullException(nameof(value));
+ SetResetLock(true);
+ HeaderParameter["Host"] = value;
+ host = new Lazy(value);
+ SetResetLock(false);
+ }
}
+
public HttpPost Post { get; } = new HttpPost();
- public List FieldAccept { get; } = new List();
- public List FieldAcceptCharset { get; } = new List();
- public List FieldAcceptEncoding { get; } = new List();
- public HttpConnectionType FieldConnection { get; set; } = HttpConnectionType.Close;
- public HttpCookie Cookie { get; } = new HttpCookie("");
+
+ private Lazy>? fieldAccept = null;
+ public ReadOnlyCollection FieldAccept
+ {
+ get
+ {
+ if (fieldAccept != null)
+ return fieldAccept.Value;
+ return (fieldAccept = new Lazy>(
+ () => new ReadOnlyCollection(
+ HeaderParameter.TryGetValue("Accept", out string value) ?
+ value.Split(
+ new[] { ',', ' ' },
+ StringSplitOptions.RemoveEmptyEntries
+ ) : new string[0]
+ )
+ )).Value;
+ }
+ set
+ {
+ _ = value ?? throw new ArgumentNullException(nameof(value));
+ var header = string.Join(", ", value);
+ SetResetLock(true);
+ HeaderParameter["Accept"] = header;
+ fieldAccept = new Lazy>(value);
+ SetResetLock(false);
+ }
+ }
+
+ private Lazy>? fieldAcceptCharset = null;
+ public ReadOnlyCollection FieldAcceptCharset
+ {
+ get
+ {
+ if (fieldAcceptCharset != null)
+ return fieldAcceptCharset.Value;
+ return (fieldAcceptCharset = new Lazy>(
+ () => new ReadOnlyCollection(
+ HeaderParameter.TryGetValue("Accept-Charset", out string value) ?
+ value.Split(
+ new[] { ',', ' ' },
+ StringSplitOptions.RemoveEmptyEntries
+ ) : new string[0]
+ )
+ )).Value;
+ }
+ set
+ {
+ _ = value ?? throw new ArgumentNullException(nameof(value));
+ var header = string.Join(", ", value);
+ SetResetLock(true);
+ HeaderParameter["Accept-Charset"] = header;
+ fieldAcceptCharset = new Lazy>(value);
+ SetResetLock(false);
+ }
+ }
+
+ private Lazy>? fieldAcceptEncoding = null;
+ public ReadOnlyCollection FieldAcceptEncoding
+ {
+ get
+ {
+ if (fieldAcceptEncoding != null)
+ return fieldAcceptEncoding.Value;
+ return (fieldAcceptEncoding = new Lazy>(
+ () => new ReadOnlyCollection(
+ HeaderParameter.TryGetValue("Accept-Encoding", out string value) ?
+ value.Split(
+ new[] { ',', ' ' },
+ StringSplitOptions.RemoveEmptyEntries
+ ) : new string[0]
+ )
+ )).Value;
+ }
+ set
+ {
+ _ = value ?? throw new ArgumentNullException(nameof(value));
+ var header = string.Join(", ", value);
+ SetResetLock(true);
+ HeaderParameter["Accept-Encoding"] = header;
+ fieldAcceptEncoding = new Lazy>(value);
+ SetResetLock(false);
+ }
+ }
+
+ private Lazy? fieldConnection = null;
+ public HttpConnectionType FieldConnection
+ {
+ get
+ {
+ if (fieldConnection != null)
+ return fieldConnection.Value;
+ return (fieldConnection = new Lazy(
+ () => HeaderParameter.TryGetValue("Connection", out string value)
+ && value.ToLower() == "keep-alive" ?
+ HttpConnectionType.KeepAlive :
+ HttpConnectionType.Close
+ )).Value;
+ }
+ set
+ {
+ SetResetLock(true);
+ switch (value)
+ {
+ case HttpConnectionType.KeepAlive:
+ HeaderParameter["Connection"] = "keep-alive";
+ break;
+ case HttpConnectionType.Close:
+ HeaderParameter["Connection"] = "close";
+ break;
+ default:
+ SetResetLock(false);
+ throw new NotSupportedException($"Unsupported connection type {value}");
+ }
+ fieldConnection = new Lazy(value);
+ SetResetLock(false);
+ }
+ }
+
+ private Lazy? cookie = null;
+ public HttpCookie Cookie
+ {
+ get
+ {
+ if (cookie != null)
+ return cookie.Value;
+ return (cookie = new Lazy(
+ () => HeaderParameter.TryGetValue("Cookie", out string value) ?
+ new HttpCookie(value) :
+ new HttpCookie("")
+ )).Value;
+ }
+ }
public string? FieldUserAgent
{
get => GetHeader("User-Agent");
- set => SetHeader("User-Agent", value);
+ set
+ {
+ SetResetLock(true);
+ SetHeader("User-Agent", value);
+ SetResetLock(false);
+ }
}
}
}
diff --git a/MaxLib.WebServer/HttpStreamDataSource.cs b/MaxLib.WebServer/HttpStreamDataSource.cs
index 436ae29..2ea7d91 100644
--- a/MaxLib.WebServer/HttpStreamDataSource.cs
+++ b/MaxLib.WebServer/HttpStreamDataSource.cs
@@ -12,14 +12,6 @@ public class HttpStreamDataSource : HttpDataSource
{
public Stream Stream { get; }
- [Obsolete]
- public bool ReadOnly { get; }
-
- [Obsolete]
- public override bool CanAcceptData => !ReadOnly && Stream.CanWrite;
-
- public override bool CanProvideData => Stream.CanRead;
-
public HttpStreamDataSource(Stream stream)
{
Stream = stream ?? throw new ArgumentNullException(nameof(stream));
@@ -30,60 +22,38 @@ public HttpStreamDataSource(Stream stream)
);
}
- [Obsolete]
- public HttpStreamDataSource(Stream stream, bool readOnly = true)
- : this(stream)
- {
- ReadOnly = readOnly;
- }
-
public override void Dispose()
=> Stream.Dispose();
public override long? Length()
=> Stream.Length;
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
+ protected override Task WriteStreamInternal(Stream stream)
{
- await Task.CompletedTask;
- Stream.Position = start;
- using (var skip = new SkipableStream(Stream, 0))
- {
- try
- {
- return skip.WriteToStream(stream,
- stop == null ? null : (long?)(stop.Value - start));
- }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
- return Stream.Position - start;
- }
- }
+ return WriteStream(stream, 0, null);
}
- [Obsolete]
- protected override async Task ReadStreamInternal(Stream stream, long? length)
+ public async Task WriteStream(Stream stream, long offset, long? count)
{
- await Task.CompletedTask.ConfigureAwait(false);
- if (ReadOnly)
- throw new NotSupportedException();
- Stream.Position = 0;
- using (var skip = new SkipableStream(Stream, 0))
+ if (Stream.CanSeek)
+ Stream.Position = offset;
+ long total = 0;
+ Memory buffer = new byte[0x8000];
+ try
{
- long readed;
- try
+ int read;
+ int job = count == null ? buffer.Length : (int)Math.Min(buffer.Length, count.Value - total);
+ while ((read = await Stream.ReadAsync(buffer[..job])) > 0)
{
- readed = skip.ReadFromStream(stream, length);
+ await stream.WriteAsync(buffer[0..read]);
+ total += read;
}
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
- readed = Stream.Position;
- }
- Stream.SetLength(readed);
- return readed;
}
+ catch (IOException)
+ {
+ WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
+ }
+ return total;
}
}
}
diff --git a/MaxLib.WebServer/HttpStringDataSource.cs b/MaxLib.WebServer/HttpStringDataSource.cs
index 6f2fd4f..c6ecb4b 100644
--- a/MaxLib.WebServer/HttpStringDataSource.cs
+++ b/MaxLib.WebServer/HttpStringDataSource.cs
@@ -29,11 +29,6 @@ public string TextEncoding
}
}
- [Obsolete]
- public override bool CanAcceptData => true;
-
- public override bool CanProvideData => true;
-
Encoding Encoder;
public HttpStringDataSource(string data)
@@ -50,38 +45,17 @@ public override void Dispose()
public override long? Length()
=> Encoder.GetByteCount(Data);
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
- {
- await Task.CompletedTask.ConfigureAwait(false);
- using (var m = new MemoryStream(Encoder.GetBytes(Data)))
- using (var skip = new SkipableStream(m, start))
- {
- try { return skip.WriteToStream(stream, stop); }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
- return m.Position;
- }
- }
- }
-
- [Obsolete]
- protected override async Task ReadStreamInternal(Stream stream, long? length)
+ protected override async Task WriteStreamInternal(Stream stream)
{
await Task.CompletedTask.ConfigureAwait(false);
- using (var m = new MemoryStream())
- using (var skip = new SkipableStream(m, 0))
+ using var m = new MemoryStream(Encoder.GetBytes(Data));
+ try { await m.CopyToAsync(stream).ConfigureAwait(false); }
+ catch (IOException)
{
- long total;
- try { total = skip.ReadFromStream(stream, length); }
- catch (IOException)
- {
- WebServerLog.Add(ServerLogType.Information, GetType(), "Receive", "Connection closed by remote Host");
- return m.Position;
- }
- Data = Encoder.GetString(m.ToArray());
- return total;
+ WebServerLog.Add(ServerLogType.Information, GetType(), "Send", "Connection closed by remote Host");
+ return m.Position;
}
+ return m.Length;
}
}
}
diff --git a/MaxLib.WebServer/IO/ReadLineOverflowException.cs b/MaxLib.WebServer/IO/ReadLineOverflowException.cs
index fbb8cd3..788e4f0 100644
--- a/MaxLib.WebServer/IO/ReadLineOverflowException.cs
+++ b/MaxLib.WebServer/IO/ReadLineOverflowException.cs
@@ -14,12 +14,5 @@ public ReadLineOverflowException(HttpStateCode state, string message) : base(mes
{
State = state;
}
- public ReadLineOverflowException(HttpStateCode state, string message, System.Exception inner) : base(message, inner)
- {
- State = state;
- }
- protected ReadLineOverflowException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
-}
\ No newline at end of file
+}
diff --git a/MaxLib.WebServer/Lazy/LazySource.cs b/MaxLib.WebServer/Lazy/LazySource.cs
index 3b8d22f..5649ee8 100644
--- a/MaxLib.WebServer/Lazy/LazySource.cs
+++ b/MaxLib.WebServer/Lazy/LazySource.cs
@@ -50,65 +50,14 @@ public override void Dispose()
s.Dispose();
}
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
+ protected override async Task WriteStreamInternal(Stream stream)
{
- using (var skip = new SkipableStream(stream, start))
+ long total = 0;
+ foreach (var s in GetAllSources())
{
- long total = 0;
- foreach (var s in GetAllSources())
- {
- if (stop != null && total >= stop.Value)
- return total;
- var end = stop == null ? null : (long?)(stop.Value - total);
- var size = s.Length();
- if (size == null)
- {
- total += await s.WriteStream(skip, 0, end).ConfigureAwait(false);
- }
- else
- {
- if (size.Value < skip.SkipBytes)
- {
- skip.Skip(size.Value);
- continue;
- }
- var leftSkip = skip.SkipBytes;
- skip.Skip(skip.SkipBytes);
- total += await s.WriteStream(skip, leftSkip, end).ConfigureAwait(false);
- }
- }
- return total;
+ total += await s.WriteStream(stream).ConfigureAwait(false);
}
+ return total;
}
-
- [Obsolete]
- protected override Task ReadStreamInternal(Stream stream, long? length)
- => throw new NotSupportedException();
-
- [Obsolete]
- public override long RangeStart
- {
- get => 0;
- set => throw new NotSupportedException();
- }
-
- [Obsolete]
- public override long? RangeEnd
- {
- get => null;
- set => throw new NotSupportedException();
- }
-
- [Obsolete]
- public override bool TransferCompleteData
- {
- get => true;
- set => throw new NotSupportedException();
- }
-
- [Obsolete]
- public override bool CanAcceptData => false;
-
- public override bool CanProvideData => true;
}
}
diff --git a/MaxLib.WebServer/MaxLib.WebServer.csproj b/MaxLib.WebServer/MaxLib.WebServer.csproj
index 61e144f..1d6f970 100644
--- a/MaxLib.WebServer/MaxLib.WebServer.csproj
+++ b/MaxLib.WebServer/MaxLib.WebServer.csproj
@@ -3,13 +3,11 @@
- net6.0;netstandard2.1
+ net8.0;net6.0
MaxLib.WebServer
garados007
Max Brauer
-
- MaxLib.Ini is a full web server written in C# that can easily integrated in your project.
-
+ README.md
MIT
https://github.com/Garados007/MaxLib.WebServer
@@ -24,9 +22,8 @@
-
-
-
+
+
@@ -36,6 +33,7 @@
+
diff --git a/MaxLib.WebServer/MaxLib.WebServer.csproj.include b/MaxLib.WebServer/MaxLib.WebServer.csproj.include
index c12b6cb..88dfa8e 100644
--- a/MaxLib.WebServer/MaxLib.WebServer.csproj.include
+++ b/MaxLib.WebServer/MaxLib.WebServer.csproj.include
@@ -2,7 +2,7 @@
- 3.6.0
+ 4.0.0
$(Version).0
$(Version).0
diff --git a/MaxLib.WebServer/MultipartRanges.cs b/MaxLib.WebServer/MultipartRanges.cs
index 453ab8c..7283e29 100644
--- a/MaxLib.WebServer/MultipartRanges.cs
+++ b/MaxLib.WebServer/MultipartRanges.cs
@@ -28,11 +28,6 @@ public static long JoinGap
}
}
- [Obsolete]
- public override bool CanAcceptData => false;
-
- public override bool CanProvideData => true;
-
[Serializable]
struct Range
{
@@ -172,14 +167,11 @@ void SinglePart()
response.StatusCode = HttpStateCode.PartialContent;
var h = response.HeaderParameter;
h["Content-Range"] = ranges[0].ToString(baseStream.Length);
- streams.Add(new HttpStreamDataSource(baseStream)
- {
-#pragma warning disable CS0618
- RangeStart = ranges[0].From,
- RangeEnd = ranges[0].To,
- TransferCompleteData = false
-#pragma warning restore CS0618
- });
+ streams.Add(new HttpPartialSource(
+ new HttpStreamDataSource(baseStream),
+ ranges[0].From,
+ ranges[0].To - ranges[0].From
+ ));
}
void MultiPart()
@@ -202,31 +194,18 @@ void MultiPart()
sb.Append("Content-Range: ");
sb.AppendLine(r.ToString(baseStream.Length));
sb.AppendLine();
- streams.Add(new HttpStringDataSource(sb.ToString())
- {
-#pragma warning disable CS0618
- TransferCompleteData = true
-#pragma warning restore CS0618
- });
- streams.Add(new HttpStreamDataSource(baseStream)
- {
-#pragma warning disable CS0618
- RangeStart = r.From,
- RangeEnd = r.To,
- TransferCompleteData = false
-#pragma warning restore CS0618
- });
+ streams.Add(new HttpStringDataSource(sb.ToString()));
+ streams.Add(new HttpPartialSource(
+ new HttpStreamDataSource(baseStream),
+ r.From,
+ r.To - r.From
+ ));
sb.Clear();
}
sb.Append("--");
sb.Append(boundary);
sb.Append("--");
- streams.Add(new HttpStringDataSource(sb.ToString())
- {
-#pragma warning disable CS0618
- TransferCompleteData = true
-#pragma warning restore CS0618
- });
+ streams.Add(new HttpStringDataSource(sb.ToString()));
}
public override long? Length()
@@ -248,39 +227,14 @@ public override void Dispose()
foreach (var s in streams) s.Dispose();
}
- protected override async Task WriteStreamInternal(Stream stream, long start, long? stop)
+ protected override async Task WriteStreamInternal(Stream stream)
{
- using (var skip = new SkipableStream(stream, start))
+ long total = 0;
+ foreach (var s in streams)
{
- long total = 0;
- foreach (var s in streams)
- {
- if (stop != null && total >= stop.Value)
- return total;
- var end = stop == null ? null : (long?)(stop.Value - total);
- var size = s.Length();
- if (size == null)
- {
- total += await s.WriteStream(skip, 0, end).ConfigureAwait(false);
- }
- else
- {
- if (size.Value < skip.SkipBytes)
- {
- skip.Skip(size.Value);
- continue;
- }
- var leftSkip = skip.SkipBytes;
- skip.Skip(skip.SkipBytes);
- total += await s.WriteStream(skip, leftSkip, end).ConfigureAwait(false);
- }
- }
- return total;
+ total += await s.WriteStream(stream).ConfigureAwait(false);
}
+ return total;
}
-
- [Obsolete]
- protected override Task ReadStreamInternal(Stream stream, long? length)
- => throw new NotSupportedException();
}
}
diff --git a/MaxLib.WebServer/Remote/MarshalContainer.cs b/MaxLib.WebServer/Remote/MarshalContainer.cs
index a67f760..21a2f97 100644
--- a/MaxLib.WebServer/Remote/MarshalContainer.cs
+++ b/MaxLib.WebServer/Remote/MarshalContainer.cs
@@ -16,19 +16,6 @@ public void SetOrigin(HttpDataSource origin)
Origin = origin ?? throw new ArgumentNullException(nameof(origin));
}
- [Obsolete]
- public bool CanAcceptData()
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.CanAcceptData;
- }
-
- public bool CanProvideData()
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.CanProvideData;
- }
-
public long? Length()
{
_ = Origin ?? throw new InvalidOperationException("Origin is not set");
@@ -41,59 +28,10 @@ public void Dispose()
Origin.Dispose();
}
- public Task WriteStream(Stream stream, long start, long? stop)
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.WriteStream(stream, start, stop);
- }
-
- [Obsolete]
- public Task ReadStream(Stream stream, long? length)
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.ReadStream(stream, length);
- }
-
- [Obsolete]
- public long? RangeEnd()
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.RangeEnd;
- }
-
- [Obsolete]
- public void RangeEnd(long? value)
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- Origin.RangeEnd = value;
- }
-
- [Obsolete]
- public long RangeStart()
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.RangeStart;
- }
-
- [Obsolete]
- public void RangeStart(long value)
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- Origin.RangeStart = value;
- }
-
- [Obsolete]
- public bool TransferCompleteData()
- {
- _ = Origin ?? throw new InvalidOperationException("Origin is not set");
- return Origin.TransferCompleteData;
- }
-
- [Obsolete]
- public void TransferCompleteData(bool value)
+ public Task WriteStream(Stream stream)
{
_ = Origin ?? throw new InvalidOperationException("Origin is not set");
- Origin.TransferCompleteData = value;
+ return Origin.WriteStream(stream);
}
public string MimeType()
diff --git a/MaxLib.WebServer/Remote/MarshalSource.cs b/MaxLib.WebServer/Remote/MarshalSource.cs
index 9befe74..e608e12 100644
--- a/MaxLib.WebServer/Remote/MarshalSource.cs
+++ b/MaxLib.WebServer/Remote/MarshalSource.cs
@@ -25,33 +25,8 @@ public MarshalSource(HttpDataSource source)
public override void Dispose()
=> Container.Dispose();
- protected override Task WriteStreamInternal(Stream stream, long start, long? stop)
- => Container.WriteStream(stream, start, stop);
-
- [Obsolete]
- protected override Task ReadStreamInternal(Stream stream, long? length)
- => Container.ReadStream(stream, length);
-
- [Obsolete]
- public override long? RangeEnd
- {
- get => Container.RangeEnd();
- set => Container.RangeEnd(value);
- }
-
- [Obsolete]
- public override long RangeStart
- {
- get => Container.RangeStart();
- set => Container.RangeStart(value);
- }
-
- [Obsolete]
- public override bool TransferCompleteData
- {
- get => Container.TransferCompleteData();
- set => Container.TransferCompleteData(value);
- }
+ protected override Task WriteStreamInternal(Stream stream)
+ => Container.WriteStream(stream);
public override string MimeType
{
@@ -59,11 +34,6 @@ public override string MimeType
set => Container.MimeType(value);
}
- [Obsolete]
- public override bool CanAcceptData => Container.CanAcceptData();
-
- public override bool CanProvideData => Container.CanProvideData();
-
public Collections.MarshalEnumerable? GetAllSources()
=> Container.Sources();
}
diff --git a/MaxLib.WebServer/SSL/DualSecureWebServer.cs b/MaxLib.WebServer/SSL/DualSecureWebServer.cs
index 185e64d..7513632 100644
--- a/MaxLib.WebServer/SSL/DualSecureWebServer.cs
+++ b/MaxLib.WebServer/SSL/DualSecureWebServer.cs
@@ -20,9 +20,7 @@ public DualSecureWebServer(DualSecureWebServerSettings settings) : base(settings
protected override async Task ClientStartListen(HttpConnection connection)
{
- if (connection.NetworkStream == null && DualSettings.Certificate != null
- && connection.NetworkClient != null
- )
+ if (connection.NetworkStream == null && connection.NetworkClient != null)
{
var peaker = new StreamPeaker(connection.NetworkClient.GetStream());
var mark = peaker.FirstByte;
diff --git a/MaxLib.WebServer/SSL/DualSecureWebServerSettings.cs b/MaxLib.WebServer/SSL/DualSecureWebServerSettings.cs
index 2aee070..5f9c6a3 100644
--- a/MaxLib.WebServer/SSL/DualSecureWebServerSettings.cs
+++ b/MaxLib.WebServer/SSL/DualSecureWebServerSettings.cs
@@ -6,13 +6,7 @@ namespace MaxLib.WebServer.SSL
{
public class DualSecureWebServerSettings : WebServerSettings
{
- public X509Certificate? Certificate { get; set; }
-
- public DualSecureWebServerSettings(string settingFolderPath)
- : base(settingFolderPath)
- {
-
- }
+ public X509Certificate Certificate { get; set; }
public DualSecureWebServerSettings(int port, int connectionTimeout, X509Certificate certificate)
: base(port, connectionTimeout)
diff --git a/MaxLib.WebServer/SSL/SecureWebServerSettings.cs b/MaxLib.WebServer/SSL/SecureWebServerSettings.cs
index dde4ff7..ec66dd1 100644
--- a/MaxLib.WebServer/SSL/SecureWebServerSettings.cs
+++ b/MaxLib.WebServer/SSL/SecureWebServerSettings.cs
@@ -1,5 +1,4 @@
-using MaxLib.Ini;
-using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography.X509Certificates;
#nullable enable
@@ -12,11 +11,6 @@ public class SecureWebServerSettings : WebServerSettings
public X509Certificate? Certificate { get; set; }
- public SecureWebServerSettings(string settingFolderPath)
- : base(settingFolderPath)
- {
- }
-
public SecureWebServerSettings(int port, int securePort, int connectionTimeout)
: base(port, connectionTimeout)
{
@@ -29,13 +23,5 @@ public SecureWebServerSettings(int securePort, int connectionTimeout)
SecurePort = securePort;
EnableUnsafePort = false;
}
-
- protected override void Load_Server(IniFile set)
- {
- base.Load_Server(set);
- var server = set.GetGroup("Server");
- SecurePort = server.GetInt32("SecurePort", 443);
- EnableUnsafePort = server.GetBool("EnableUnsafePort", true);
- }
}
}
diff --git a/MaxLib.WebServer/Server.cs b/MaxLib.WebServer/Server.cs
index e45b15d..c34c8b5 100644
--- a/MaxLib.WebServer/Server.cs
+++ b/MaxLib.WebServer/Server.cs
@@ -67,18 +67,16 @@ public Server(WebServerSettings settings)
///
/// Initialize the server with a basic set of web services. These are: , , , , and .
- /// With these you have basic functionality and a working web server that can deliver 404
- /// answers for every request.
+ /// cref="Services.HttpRequestParser" />, ,
+ /// , and
+ /// .
With these you have basic functionality and a
+ /// working web server that can deliver 404 answers for every request.
///
public virtual void InitialDefault()
{
//Pre parse request
AddWebService(new Services.HttpRequestParser());
//post parse request
- AddWebService(new Services.HttpHeaderPostParser());
AddWebService(new Services.HttpHeaderSpecialAction());
//pre create document
AddWebService(new Services.Http404Service());
diff --git a/MaxLib.WebServer/Services/HttpHeaderPostParser.cs b/MaxLib.WebServer/Services/HttpHeaderPostParser.cs
deleted file mode 100644
index 018d2d1..0000000
--- a/MaxLib.WebServer/Services/HttpHeaderPostParser.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System;
-using System.Threading.Tasks;
-
-#nullable enable
-
-namespace MaxLib.WebServer.Services
-{
- ///
- /// WebServiceType.PostParseRequest: Ließt alle Informationen aus dem Header aus und analysiert diese.
- /// Die Headerklasse wird für die weitere Verwendung vorbereitet.
- ///
- public class HttpHeaderPostParser : WebService
- {
- ///
- /// WebServiceType.PostParseRequest: Ließt alle Informationen aus dem Header aus und analysiert diese.
- /// Die Headerklasse wird für die weitere Verwendung vorbereitet.
- ///
- public HttpHeaderPostParser()
- : base(ServerStage.ParseRequest)
- {
- Priority = WebServicePriority.VeryHigh;
- }
-
- public override async Task ProgressTask(WebProgressTask task)
- {
- _ = task ?? throw new ArgumentNullException(nameof(task));
-
- var header = task.Request;
- //Accept
- if (header.HeaderParameter.TryGetValue("Accept", out string? value))
- {
- header.FieldAccept.AddRange(value.Split(
- new[] { ',', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries));
- }
- //Accept-Encoding
- if (header.HeaderParameter.TryGetValue("Accept-Encoding", out value))
- {
- header.FieldAcceptEncoding.AddRange(value.Split(
- new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries));
- }
- //Connection
- if (header.HeaderParameter.TryGetValue("Connection", out value))
- {
- if (value.ToLower() == "keep-alive")
- header.FieldConnection = HttpConnectionType.KeepAlive;
- }
- //Host
- if (header.HeaderParameter.TryGetValue("Host", out value))
- {
- header.Host = value;
- }
- //Cookie
- if (header.HeaderParameter.TryGetValue("Cookie", out value))
- {
- header.Cookie.SetRequestCookieString(value);
- }
-
- await Task.CompletedTask.ConfigureAwait(false);
- }
-
- public override bool CanWorkWith(WebProgressTask task)
- => true;
- }
-}
diff --git a/MaxLib.WebServer/Services/StandardDocumentLoader.cs b/MaxLib.WebServer/Services/StandardDocumentLoader.cs
index 4ddfa2e..c9eb835 100644
--- a/MaxLib.WebServer/Services/StandardDocumentLoader.cs
+++ b/MaxLib.WebServer/Services/StandardDocumentLoader.cs
@@ -9,6 +9,7 @@ namespace MaxLib.WebServer.Services
/// WebServiceType.PreCreateDocument: Stellt ein festdefiniertes Dokument bereit. Dies ist unabhängig vom
/// angeforderten Pfad.
///
+ [Obsolete("Define your own endpoint or use Http404Service")]
public class StandardDocumentLoader : WebService
{
///
diff --git a/MaxLib.WebServer/WebServerSettings.cs b/MaxLib.WebServer/WebServerSettings.cs
index 187876b..5ec0d79 100644
--- a/MaxLib.WebServer/WebServerSettings.cs
+++ b/MaxLib.WebServer/WebServerSettings.cs
@@ -1,7 +1,4 @@
-using MaxLib.Ini;
-using System;
-using System.Collections.Generic;
-using System.IO;
+using System;
using System.Net;
#nullable enable
@@ -50,71 +47,6 @@ public TimeSpan ConnectionDelay
public bool Debug_WriteRequests = false;
public bool Debug_LogConnections = false;
- public Dictionary DefaultFileMimeAssociation { get; }
- = new Dictionary();
-
- protected enum SettingTypes
- {
- MimeAssociation,
- ServerSettings
- }
-
- public string? SettingsPath { get; private set; }
-
- public virtual void LoadSettingFromData(string data)
- {
- _ = data ?? throw new ArgumentNullException(nameof(data));
- var sf = new Ini.Parser.IniParser().ParseFromString(data);
- if (sf.GetGroup("Mime") != null)
- Load_Mime(sf);
- if (sf.GetGroup("Server") != null)
- Load_Server(sf);
- }
-
- public virtual void LoadSetting(string path)
- {
- _ = path ?? throw new ArgumentNullException(nameof(path));
- SettingsPath = path;
- var sf = new Ini.Parser.IniParser().Parse(path);
- if (sf.GetGroup("Mime") != null)
- Load_Mime(sf);
- if (sf.GetGroup("Server") != null)
- Load_Server(sf);
- }
-
- protected virtual void Load_Mime(IniFile set)
- {
- DefaultFileMimeAssociation.Clear();
- var gr = set.GetGroup("Mime").GetAll();
- foreach (IniOption keypair in gr)
- DefaultFileMimeAssociation[keypair.Name] = keypair.String;
- }
-
- protected virtual void Load_Server(IniFile set)
- {
- var server = set.GetGroup("Server");
- Port = server.GetInt32("Port", 80);
- if (Port <= 0 || Port >= 0xffff)
- Port = 80;
- ConnectionTimeout = server.GetInt32("ConnectionTimeout", 2000);
- if (ConnectionTimeout < 0)
- ConnectionTimeout = 2000;
- }
-
- public WebServerSettings(string settingFolderPath)
- {
- _ = settingFolderPath ?? throw new ArgumentNullException(nameof(settingFolderPath));
- if (Directory.Exists(settingFolderPath))
- foreach (var file in Directory.GetFiles(settingFolderPath))
- {
- if (file.EndsWith(".ini"))
- LoadSetting(file);
- }
- else if (File.Exists(settingFolderPath))
- LoadSetting(settingFolderPath);
- else throw new DirectoryNotFoundException();
- }
-
public WebServerSettings(int port, int connectionTimeout)
{
if (port <= 0 || port >= 0xffff)
diff --git a/MaxLib.WebServer/WebServerTaskCreator.cs b/MaxLib.WebServer/WebServerTaskCreator.cs
index d027580..b462439 100644
--- a/MaxLib.WebServer/WebServerTaskCreator.cs
+++ b/MaxLib.WebServer/WebServerTaskCreator.cs
@@ -1,4 +1,5 @@
-using System;
+using System.Collections.ObjectModel;
+using System;
using System.IO;
using System.Threading.Tasks;
@@ -58,8 +59,10 @@ public void SetPost(WebProgressTask task, ReadOnlyMemory post, string mime
public void SetAccept(string[]? acceptTypes = null, string[]? encoding = null)
{
- if (acceptTypes != null) Task.Request.FieldAccept.AddRange(acceptTypes);
- if (encoding != null) Task.Request.FieldAcceptEncoding.AddRange(encoding);
+ if (acceptTypes != null)
+ Task.Request.FieldAccept = new ReadOnlyCollection(acceptTypes);
+ if (encoding != null)
+ Task.Request.FieldAcceptEncoding = new ReadOnlyCollection(encoding);
}
public void SetHost(string host)
diff --git a/MaxLib.WebServer/WebSocket/TooLargePayloadException.cs b/MaxLib.WebServer/WebSocket/TooLargePayloadException.cs
index 63ccf52..2a8105f 100644
--- a/MaxLib.WebServer/WebSocket/TooLargePayloadException.cs
+++ b/MaxLib.WebServer/WebSocket/TooLargePayloadException.cs
@@ -10,8 +10,5 @@ public class TooLargePayloadException : Exception
public TooLargePayloadException() { }
public TooLargePayloadException(string message) : base(message) { }
public TooLargePayloadException(string message, Exception inner) : base(message, inner) { }
- protected TooLargePayloadException(
- System.Runtime.Serialization.SerializationInfo info,
- System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}
diff --git a/example/MaxLib.WebServer.Example/MaxLib.WebServer.Example.csproj b/example/MaxLib.WebServer.Example/MaxLib.WebServer.Example.csproj
index c3861a3..5c7ceec 100644
--- a/example/MaxLib.WebServer.Example/MaxLib.WebServer.Example.csproj
+++ b/example/MaxLib.WebServer.Example/MaxLib.WebServer.Example.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp3.1
+ net8.0
diff --git a/example/MaxLib.WebServer.Example/Program.cs b/example/MaxLib.WebServer.Example/Program.cs
index 1ee7b8d..143aa0f 100644
--- a/example/MaxLib.WebServer.Example/Program.cs
+++ b/example/MaxLib.WebServer.Example/Program.cs
@@ -1,23 +1,23 @@
using System;
+using System.Threading.Tasks;
using MaxLib.WebServer.Services;
namespace MaxLib.WebServer.Example
{
class Program
{
- static void Main(string[] args)
+ static async Task Main(string[] args)
{
WebServerLog.LogAdded += WebServerLog_LogAdded;
- var server = new Server(new WebServerSettings(8000, 5000));
+ using var server = new Server(new WebServerSettings(8000, 5000));
// add services
server.AddWebService(new HttpRequestParser());
- server.AddWebService(new HttpHeaderPostParser());
server.AddWebService(new HttpHeaderSpecialAction());
- server.AddWebService(new StandardDocumentLoader() { Document = "Hello World!" });
+ server.AddWebService(new Http404Service());
server.AddWebService(new HttpResponseCreator());
server.AddWebService(new HttpSender());
- // start server
- server.Start();
+ // run server until cancel received
+ await server.RunAsync();
}
private static void WebServerLog_LogAdded(ServerLogItem item)
diff --git a/MaxLib.WebServer.WebSocket.Echo/EchoConnection.cs b/example/MaxLib.WebServer.WebSocket.Echo/EchoConnection.cs
similarity index 100%
rename from MaxLib.WebServer.WebSocket.Echo/EchoConnection.cs
rename to example/MaxLib.WebServer.WebSocket.Echo/EchoConnection.cs
diff --git a/MaxLib.WebServer.WebSocket.Echo/EchoEndpoint.cs b/example/MaxLib.WebServer.WebSocket.Echo/EchoEndpoint.cs
similarity index 100%
rename from MaxLib.WebServer.WebSocket.Echo/EchoEndpoint.cs
rename to example/MaxLib.WebServer.WebSocket.Echo/EchoEndpoint.cs
diff --git a/MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj b/example/MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj
similarity index 52%
rename from MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj
rename to example/MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj
index fc78de2..5c7ceec 100644
--- a/MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj
+++ b/example/MaxLib.WebServer.WebSocket.Echo/MaxLib.WebServer.WebSocket.Echo.csproj
@@ -2,11 +2,11 @@
Exe
- netcoreapp3.1
+ net8.0
-
+
diff --git a/MaxLib.WebServer.WebSocket.Echo/Program.cs b/example/MaxLib.WebServer.WebSocket.Echo/Program.cs
similarity index 64%
rename from MaxLib.WebServer.WebSocket.Echo/Program.cs
rename to example/MaxLib.WebServer.WebSocket.Echo/Program.cs
index 39987d1..95184d1 100644
--- a/MaxLib.WebServer.WebSocket.Echo/Program.cs
+++ b/example/MaxLib.WebServer.WebSocket.Echo/Program.cs
@@ -1,5 +1,6 @@
using MaxLib.WebServer.Services;
using System;
+using System.Threading.Tasks;
#nullable enable
@@ -7,27 +8,21 @@ namespace MaxLib.WebServer.WebSocket.Echo
{
class Program
{
- static void Main()
+ static async Task Main()
{
WebServerLog.LogAdded += WebServerLog_LogAdded;
- var server = new Server(new WebServerSettings(8000, 5000));
+ using var server = new Server(new WebServerSettings(8000, 5000));
// add services
server.AddWebService(new HttpRequestParser());
- server.AddWebService(new HttpHeaderPostParser());
server.AddWebService(new HttpHeaderSpecialAction());
server.AddWebService(new HttpResponseCreator());
server.AddWebService(new HttpSender());
// setup web socket
- var websocket = new WebSocketService();
+ using var websocket = new WebSocketService();
websocket.Add(new EchoEndpoint());
server.AddWebService(websocket);
- // start server
- server.Start();
- // wait for console quit
- while (Console.ReadKey().Key != ConsoleKey.Q) ;
- // close
- server.Stop();
- websocket.Dispose();
+ // run server until cancel received
+ await server.RunAsync();
}
private static void WebServerLog_LogAdded(ServerLogItem item)
diff --git a/MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs b/tests/MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs
similarity index 99%
rename from MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs
rename to tests/MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs
index be8a640..33b738b 100644
--- a/MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs
+++ b/tests/MaxLib.WebServer.Test/Api/Rest/TestRestActionEndpoint.cs
@@ -6,6 +6,7 @@
namespace MaxLib.WebServer.Test.Api.Rest
{
+ [Obsolete]
[TestClass]
public class TestRestActionEndpoint
{
diff --git a/MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs b/tests/MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs
similarity index 99%
rename from MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs
rename to tests/MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs
index 6866be4..46003a8 100644
--- a/MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs
+++ b/tests/MaxLib.WebServer.Test/Api/Rest/TestRestApiFactory.cs
@@ -2,9 +2,11 @@
using MaxLib.WebServer.Api.Rest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
+using System;
namespace MaxLib.WebServer.Test.Api.Rest
{
+ [Obsolete]
[TestClass]
public class TestRestApiFactory
{
diff --git a/MaxLib.WebServer.Test/Builder/SingleService.cs b/tests/MaxLib.WebServer.Test/Builder/SingleService.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Builder/SingleService.cs
rename to tests/MaxLib.WebServer.Test/Builder/SingleService.cs
diff --git a/MaxLib.WebServer.Test/Builder/TestSingleService.cs b/tests/MaxLib.WebServer.Test/Builder/TestSingleService.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Builder/TestSingleService.cs
rename to tests/MaxLib.WebServer.Test/Builder/TestSingleService.cs
diff --git a/MaxLib.WebServer.Test/IO/TestNetworkReader.cs b/tests/MaxLib.WebServer.Test/IO/TestNetworkReader.cs
similarity index 100%
rename from MaxLib.WebServer.Test/IO/TestNetworkReader.cs
rename to tests/MaxLib.WebServer.Test/IO/TestNetworkReader.cs
diff --git a/tests/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj b/tests/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj
new file mode 100644
index 0000000..ff5d126
--- /dev/null
+++ b/tests/MaxLib.WebServer.Test/MaxLib.WebServer.Test.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ net8.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MaxLib.WebServer.Test/Services/TestHttpHeaderSpecialAction.cs b/tests/MaxLib.WebServer.Test/Services/TestHttpHeaderSpecialAction.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Services/TestHttpHeaderSpecialAction.cs
rename to tests/MaxLib.WebServer.Test/Services/TestHttpHeaderSpecialAction.cs
diff --git a/MaxLib.WebServer.Test/Services/TestHttpRequestParser.cs b/tests/MaxLib.WebServer.Test/Services/TestHttpRequestParser.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Services/TestHttpRequestParser.cs
rename to tests/MaxLib.WebServer.Test/Services/TestHttpRequestParser.cs
diff --git a/MaxLib.WebServer.Test/Services/TestHttpResponseCreator.cs b/tests/MaxLib.WebServer.Test/Services/TestHttpResponseCreator.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Services/TestHttpResponseCreator.cs
rename to tests/MaxLib.WebServer.Test/Services/TestHttpResponseCreator.cs
diff --git a/MaxLib.WebServer.Test/Services/TestHttpSender.cs b/tests/MaxLib.WebServer.Test/Services/TestHttpSender.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Services/TestHttpSender.cs
rename to tests/MaxLib.WebServer.Test/Services/TestHttpSender.cs
diff --git a/MaxLib.WebServer.Test/Services/TestHttpHeaderPostParser.cs b/tests/MaxLib.WebServer.Test/TestHttpRequestHeader.cs
similarity index 64%
rename from MaxLib.WebServer.Test/Services/TestHttpHeaderPostParser.cs
rename to tests/MaxLib.WebServer.Test/TestHttpRequestHeader.cs
index 3f39bba..6020380 100644
--- a/MaxLib.WebServer.Test/Services/TestHttpHeaderPostParser.cs
+++ b/tests/MaxLib.WebServer.Test/TestHttpRequestHeader.cs
@@ -1,12 +1,13 @@
using MaxLib.WebServer.Services;
using MaxLib.WebServer.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
using System.Threading.Tasks;
namespace MaxLib.WebServer.Test.Services
{
[TestClass]
- public class TestHttpHeaderPostParser
+ public class TestHttpRequestHeader
{
TestWebServer server;
TestTask test;
@@ -15,7 +16,6 @@ public class TestHttpHeaderPostParser
public void Init()
{
server = new TestWebServer();
- server.AddWebService(new HttpHeaderPostParser());
test = new TestTask(server)
{
CurrentStage = ServerStage.ParseRequest,
@@ -24,21 +24,18 @@ public void Init()
}
[TestMethod]
- public async Task TestAccept()
+ public void TestAccept()
{
test.Request.HeaderParameter.Add("Accept", "text/css,*/*;q=0.1");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
- Assert.AreEqual(3, test.Request.FieldAccept.Count);
+ Assert.AreEqual(2, test.Request.FieldAccept.Count);
Assert.AreEqual("text/css", test.Request.FieldAccept[0]);
- Assert.AreEqual("*/*", test.Request.FieldAccept[1]);
- Assert.AreEqual("q=0.1", test.Request.FieldAccept[2]);
+ Assert.AreEqual("*/*;q=0.1", test.Request.FieldAccept[1]);
}
[TestMethod]
- public async Task TestAcceptEncoding()
+ public void TestAcceptEncoding()
{
test.Request.HeaderParameter.Add("Accept-Encoding", "gzip, deflate, br");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
Assert.AreEqual(3, test.Request.FieldAcceptEncoding.Count);
Assert.AreEqual("gzip", test.Request.FieldAcceptEncoding[0]);
Assert.AreEqual("deflate", test.Request.FieldAcceptEncoding[1]);
@@ -46,34 +43,30 @@ public async Task TestAcceptEncoding()
}
[TestMethod]
- public async Task TestConnection()
+ public void TestConnection()
{
test.Request.HeaderParameter.Add("Connection", "keep-alive");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
Assert.AreEqual(HttpConnectionType.KeepAlive, test.Request.FieldConnection);
}
[TestMethod]
- public async Task TestConnectionClose()
+ public void TestConnectionClose()
{
test.Request.HeaderParameter.Add("Connection", "close");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
Assert.AreEqual(HttpConnectionType.Close, test.Request.FieldConnection);
}
[TestMethod]
- public async Task TestHost()
+ public void TestHost()
{
test.Request.HeaderParameter.Add("Host", "test.domain");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
Assert.AreEqual("test.domain", test.Request.Host);
}
[TestMethod]
- public async Task TestCookie()
+ public void TestCookie()
{
test.Request.HeaderParameter.Add("Cookie", "key1=value1; key2= value2;");
- await new HttpHeaderPostParser().ProgressTask(test.Task).ConfigureAwait(false);
Assert.AreEqual("key1=value1; key2= value2;", test.Request.Cookie.CompleteRequestCookie);
}
}
diff --git a/MaxLib.WebServer.Test/Testing/TestTestTask.cs b/tests/MaxLib.WebServer.Test/Testing/TestTestTask.cs
similarity index 100%
rename from MaxLib.WebServer.Test/Testing/TestTestTask.cs
rename to tests/MaxLib.WebServer.Test/Testing/TestTestTask.cs
diff --git a/MaxLib.WebServer.Test/WebSocket/FrameParsing.cs b/tests/MaxLib.WebServer.Test/WebSocket/FrameParsing.cs
similarity index 100%
rename from MaxLib.WebServer.Test/WebSocket/FrameParsing.cs
rename to tests/MaxLib.WebServer.Test/WebSocket/FrameParsing.cs