Changes recommended by Rider/Resharper

This commit is contained in:
2022-04-08 00:59:51 +02:00
parent 105cec55d4
commit f7c1a581e7
15 changed files with 233 additions and 99 deletions

13
.idea/.idea.VAR.HttpServer/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/.idea.VAR.Json.iml
/modules.xml
/projectSettingsUpdater.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -3,15 +3,15 @@ using System.Diagnostics;
namespace VAR.HttpServer.MiniServerTest namespace VAR.HttpServer.MiniServerTest
{ {
internal class Program public static class Program
{ {
private static void Main(string[] args) private static void Main()
{ {
HttpServer httpServer = new HttpServer HttpServer httpServer = new HttpServer
{ {
Port = 3000, Port = 3000,
Handler = new HelloWorldHttpHandler(), Handler = new HelloWorldHttpHandler(),
LogDegugMessage = (msg) => Console.WriteLine("DEBUG: {0}", msg), LogDebugMessage = (msg) => Console.WriteLine("DEBUG: {0}", msg),
LogException = (ex) => LogException = (ex) =>
{ {
Console.WriteLine("!!!!! Exception !!!!"); Console.WriteLine("!!!!! Exception !!!!");
@@ -19,14 +19,14 @@ namespace VAR.HttpServer.MiniServerTest
Console.WriteLine("StackTrace: {0}", ex.StackTrace); Console.WriteLine("StackTrace: {0}", ex.StackTrace);
} }
}; };
Console.Title = string.Format("MiniHTTPServer@{0}", httpServer.Port); Console.Title = $"MiniHTTPServer@{httpServer.Port}";
Console.WriteLine("HTTP Server started on {0} port", httpServer.Port); Console.WriteLine("HTTP Server started on {0} port", httpServer.Port);
httpServer.Start(); httpServer.Start();
Process proc = Process.Start(string.Format("http://localhost:{0}", httpServer.Port)); Process.Start($"http://localhost:{httpServer.Port}");
} }
public class HelloWorldHttpHandler : IHttpHandler private class HelloWorldHttpHandler : IHttpHandler
{ {
public void HandleRequest(HttpProcessor p) public void HandleRequest(HttpProcessor p)
{ {
@@ -42,7 +42,7 @@ namespace VAR.HttpServer.MiniServerTest
{ {
greetedName = "World"; greetedName = "World";
} }
string strGreeting = string.Format("Hello {0}!", greetedName); string strGreeting = $"Hello {greetedName}!";
// Render // Render
p.ResponseSuccess(); p.ResponseSuccess();

View File

@@ -1,11 +1,11 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[assembly: AssemblyTitle("VAR.HttpServerTests")] [assembly: AssemblyTitle("VAR.HttpServer.Tests")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("VAR")] [assembly: AssemblyCompany("VAR")]
[assembly: AssemblyProduct("VAR.HttpServerTests")] [assembly: AssemblyProduct("VAR.HttpServer.Tests")]
[assembly: AssemblyCopyright("Copyright © VAR 2020")] [assembly: AssemblyCopyright("Copyright © VAR 2020")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@@ -6,8 +6,8 @@
<ProjectGuid>{1D73D51B-D094-4775-93A4-A26F8B66C167}</ProjectGuid> <ProjectGuid>{1D73D51B-D094-4775-93A4-A26F8B66C167}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VAR.HttpServerTests</RootNamespace> <RootNamespace>VAR.HttpServer.Tests</RootNamespace>
<AssemblyName>VAR.HttpServerTests</AssemblyName> <AssemblyName>VAR.HttpServer.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

View File

@@ -7,7 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.HttpServer", "VAR.HttpS
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.HttpServer.MiniServerTest", "VAR.HttpServer.MiniServerTest\VAR.HttpServer.MiniServerTest.csproj", "{6BD47B75-3DC2-4559-9311-E3D8117D4A89}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.HttpServer.MiniServerTest", "VAR.HttpServer.MiniServerTest\VAR.HttpServer.MiniServerTest.csproj", "{6BD47B75-3DC2-4559-9311-E3D8117D4A89}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.HttpServerTests", "VAR.HttpServerTests\VAR.HttpServerTests.csproj", "{1D73D51B-D094-4775-93A4-A26F8B66C167}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VAR.HttpServer.Tests", "VAR.HttpServer.Tests\VAR.HttpServer.Tests.csproj", "{1D73D51B-D094-4775-93A4-A26F8B66C167}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -0,0 +1,58 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">NotRequired</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_MULTILINE_LISTS/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/TRAILING_COMMA_IN_SINGLELINE_LISTS/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_BLOCK_ARRANGEMENT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_EMBEDDED_BLOCK_ON_SAME_LINE/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/HtmlFormatter/ALLOW_FAR_ALIGNMENT/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/HtmlFormatter/NormalizeTagNames/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/HtmlFormatter/ProcessingInstructionAttributeIndenting/@EntryValue">OneStep</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/HtmlFormatter/TagAttributeIndenting/@EntryValue">OneStep</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/HtmlFormatter/TagSpaceBeforeHeaderEnd1/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForOtherTypes/@EntryValue">UseVarWhenEvident</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AES/@EntryIndexedValue">AES</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AM/@EntryIndexedValue">AM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AUX/@EntryIndexedValue">AUX</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DC/@EntryIndexedValue">DC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DES/@EntryIndexedValue">DES</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EPM/@EntryIndexedValue">EPM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GDI/@EntryIndexedValue">GDI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RECT/@EntryIndexedValue">RECT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RGB/@EntryIndexedValue">RGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SCART/@EntryIndexedValue">SCART</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SPDIF/@EntryIndexedValue">SPDIF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SRCCOPY/@EntryIndexedValue">SRCCOPY</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TCP/@EntryIndexedValue">TCP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=USB/@EntryIndexedValue">USB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VAR/@EntryIndexedValue">VAR</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WMIC/@EntryIndexedValue">WMIC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=YRYBY/@EntryIndexedValue">YRYBY</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb"&gt;&lt;ExtraRule Prefix="T" Suffix="" Style="AaBb_AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Interfaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=LocalConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Locals/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Method/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Parameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Property/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PublicFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/SweaWarningsMode/@EntryValue">ShowAndRun</s:String></wpf:ResourceDictionary>

View File

@@ -10,49 +10,65 @@ namespace VAR.HttpServer
{ {
private static readonly int MaxPostSize = 10 * 1024 * 1024; // 10MB private static readonly int MaxPostSize = 10 * 1024 * 1024; // 10MB
private TcpClient _socket; private readonly TcpClient _socket;
public TcpClient Socket { get { return _socket; } }
private IHttpHandler _handler; public TcpClient Socket => _socket;
public IHttpHandler Handler { get { return _handler; } }
private readonly Action<string> _logDebugMessage = null; private readonly IHttpHandler _handler;
private readonly Action<Exception> _logException = null; public IHttpHandler Handler => _handler;
// ReSharper disable once NotAccessedField.Local
private readonly Action<string> _logDebugMessage;
private readonly Action<Exception> _logException;
private Stream _inputStream; private Stream _inputStream;
private StreamWriter _outputStream; private StreamWriter _outputStream;
public StreamWriter OutputStream { get { return _outputStream; } }
public StreamWriter OutputStream => _outputStream;
private string _httpRequest; private string _httpRequest;
public string HttpRequest => _httpRequest;
private string _httpMethod; private string _httpMethod;
public string HttpMethod { get { return _httpMethod; } }
public string HttpMethod => _httpMethod;
private string _httpResource; private string _httpResource;
public string HttpResource { get { return _httpResource; } }
public string HttpResource => _httpResource;
private string _httpResourceLowercase; private string _httpResourceLowercase;
public string HttpResourceLowercase { get { return _httpResourceLowercase; } }
public string HttpResourceLowercase => _httpResourceLowercase;
private string _httpQuery; private string _httpQuery;
public string HttpQuery { get { return _httpQuery; } }
public string HttpQuery => _httpQuery;
private string _httpProtocolVersionString; private string _httpProtocolVersionString;
private Dictionary<string, string> _httpHeaders = new Dictionary<string, string>(); public string HttpProtocolVersionString => _httpProtocolVersionString;
public Dictionary<string, string> HttpHeader { get { return _httpHeaders; } }
private readonly Dictionary<string, string> _httpHeaders = new Dictionary<string, string>();
public Dictionary<string, string> HttpHeader => _httpHeaders;
private string _postString; private string _postString;
public string PostString { get { return _postString; } }
private Dictionary<string, string> _httpParams = new Dictionary<string, string>(); public string PostString => _postString;
public Dictionary<string, string> HttpParams { get { return _httpParams; } }
public bool IsPostback { get { return _httpMethod.ToUpper().Equals("POST"); } } private readonly Dictionary<string, string> _httpParams = new Dictionary<string, string>();
public HttpProcessor(TcpClient s, IHttpHandler handler, Action<string> logDebugMessage, Action<Exception> logException) public Dictionary<string, string> HttpParams => _httpParams;
public bool IsPostback => _httpMethod.ToUpper().Equals("POST");
public HttpProcessor(TcpClient s, IHttpHandler handler, Action<string> logDebugMessage,
Action<Exception> logException)
{ {
_socket = s; _socket = s;
_handler = handler; _handler = handler;
@@ -87,6 +103,7 @@ namespace VAR.HttpServer
ResponseServerError(); ResponseServerError();
throw; throw;
} }
_outputStream.Flush(); _outputStream.Flush();
_inputStream = null; _inputStream = null;
_outputStream = null; _outputStream = null;
@@ -100,16 +117,23 @@ namespace VAR.HttpServer
private string StreamReadLine(Stream inputStream) private string StreamReadLine(Stream inputStream)
{ {
int next_char;
string data = string.Empty; string data = string.Empty;
while (true) while (true)
{ {
next_char = inputStream.ReadByte(); int nextChar = inputStream.ReadByte();
if (next_char == '\n') { break; } if (nextChar == '\n') { break; }
if (next_char == '\r') { continue; }
if (next_char == -1) { Thread.Sleep(1); continue; }; if (nextChar == '\r') { continue; }
data += Convert.ToChar(next_char);
if (nextChar == -1)
{
Thread.Sleep(1);
continue;
}
data += Convert.ToChar(nextChar);
} }
return data; return data;
} }
@@ -121,6 +145,7 @@ namespace VAR.HttpServer
{ {
throw new Exception("invalid HTTP request line"); throw new Exception("invalid HTTP request line");
} }
_httpRequest = request; _httpRequest = request;
_httpMethod = tokens[0].ToUpper(); _httpMethod = tokens[0].ToUpper();
_httpResource = tokens[1]; _httpResource = tokens[1];
@@ -132,8 +157,9 @@ namespace VAR.HttpServer
int idx = _httpResource.IndexOf('?'); int idx = _httpResource.IndexOf('?');
_httpQuery = _httpResource.Substring(idx + 1); _httpQuery = _httpResource.Substring(idx + 1);
_httpResource = _httpResource.Substring(0, idx); _httpResource = _httpResource.Substring(0, idx);
ReadParms(_httpQuery); ReadParameters(_httpQuery);
} }
_httpResourceLowercase = _httpResource.ToLower(); _httpResourceLowercase = _httpResource.ToLower();
} }
@@ -150,8 +176,9 @@ namespace VAR.HttpServer
int separator = line.IndexOf(':'); int separator = line.IndexOf(':');
if (separator == -1) if (separator == -1)
{ {
throw new Exception(string.Format("Invalid HTTP header line: {0}", line)); throw new Exception($"Invalid HTTP header line: {line}");
} }
string name = line.Substring(0, separator); string name = line.Substring(0, separator);
int pos = separator + 1; int pos = separator + 1;
while ((pos < line.Length) && (line[pos] == ' ')) while ((pos < line.Length) && (line[pos] == ' '))
@@ -168,55 +195,52 @@ namespace VAR.HttpServer
private void ReadPostData() private void ReadPostData()
{ {
int contentLen = 0;
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
if (_httpHeaders.ContainsKey("Content-Length")) if (_httpHeaders.ContainsKey("Content-Length"))
{ {
contentLen = Convert.ToInt32(_httpHeaders["Content-Length"]); int contentLen = Convert.ToInt32(_httpHeaders["Content-Length"]);
if (contentLen > MaxPostSize) if (contentLen > MaxPostSize)
{ {
throw new Exception(string.Format("POST Content-Length({0}) > MaxPostSize({1})", contentLen, MaxPostSize)); throw new Exception($"POST Content-Length({contentLen}) > MaxPostSize({MaxPostSize})");
} }
byte[] buf = new byte[BufferSize]; byte[] buf = new byte[BufferSize];
int to_read = contentLen; int toRead = contentLen;
while (to_read > 0) while (toRead > 0)
{ {
int numread = _inputStream.Read(buf, 0, Math.Min(BufferSize, to_read)); int numRead = _inputStream.Read(buf, 0, Math.Min(BufferSize, toRead));
if (numread == 0) if (numRead == 0)
{ {
if (to_read == 0) throw new Exception("Client disconnected during POST");
{
break;
}
else
{
throw new Exception("Client disconnected during POST");
}
} }
to_read -= numread;
ms.Write(buf, 0, numread); toRead -= numRead;
ms.Write(buf, 0, numRead);
} }
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
} }
_postString = new StreamReader(ms).ReadToEnd(); _postString = new StreamReader(ms).ReadToEnd();
if (string.IsNullOrEmpty(_postString) == false) if (string.IsNullOrEmpty(_postString) == false)
{ {
ReadParms(_postString); ReadParameters(_postString);
} }
} }
private void ReadParms(string parms) private void ReadParameters(string strParameters)
{ {
string[] parmPairs = parms.Split('&'); string[] parameterPairs = strParameters.Split('&');
foreach (string parmPair in parmPairs) foreach (string parameterPair in parameterPairs)
{ {
string[] tokens = parmPair.Split('='); string[] tokens = parameterPair.Split('=');
string key = HttpUtility.UrlDecode(tokens[0]); string key = HttpUtility.UrlDecode(tokens[0]);
string value = string.Empty; string value = string.Empty;
if (tokens.Length > 1) if (tokens.Length > 1)
{ {
value = HttpUtility.UrlDecode(tokens[1]); value = HttpUtility.UrlDecode(tokens[1]);
} }
if (_httpParams.ContainsKey(key)) if (_httpParams.ContainsKey(key))
{ {
_httpParams[key] = value; _httpParams[key] = value;
@@ -233,7 +257,7 @@ namespace VAR.HttpServer
try try
{ {
_outputStream.WriteLine("HTTP/1.0 200 OK"); _outputStream.WriteLine("HTTP/1.0 200 OK");
_outputStream.WriteLine(string.Format("Content-Type: {0}", contentType)); _outputStream.WriteLine($"Content-Type: {contentType}");
_outputStream.WriteLine("Connection: close"); _outputStream.WriteLine("Connection: close");
_outputStream.WriteLine(""); _outputStream.WriteLine("");
} }

View File

@@ -7,36 +7,48 @@ namespace VAR.HttpServer
{ {
public class HttpServer public class HttpServer
{ {
protected int _port = 8000; private int _port = 8000;
public int Port public int Port
{ {
get { return _port; } get => _port;
set set
{ {
if (_isActive) { throw new Exception("HttpServer: Can't set port while active"); } if (_isActive) { throw new Exception("HttpServer: Can't set port while active"); }
_port = value; _port = value;
} }
} }
private TcpListener _listener = null; private TcpListener _listener;
private Thread _thread = null; private Thread _thread;
private bool _isActive = false; private bool _isActive;
public bool IsActive { get { return _isActive; } }
public bool IsActive => _isActive;
private IHttpHandler _handler;
private IHttpHandler _handler = null;
public IHttpHandler Handler public IHttpHandler Handler
{ {
get { return _handler; } get => _handler;
set { _handler = value; } set => _handler = value;
} }
private Action<string> _logDebugMessage = null; private Action<string> _logDebugMessage;
public Action<string> LogDegugMessage { set { _logDebugMessage = value; } }
private Action<Exception> _logException = null; public Action<string> LogDebugMessage
public Action<Exception> LogException { set { _logException = value; } } {
set => _logDebugMessage = value;
}
private Action<Exception> _logException;
public Action<Exception> LogException
{
set => _logException = value;
}
private void ListenConnections() private void ListenConnections()
{ {
@@ -45,10 +57,12 @@ namespace VAR.HttpServer
while (_isActive) while (_isActive)
{ {
TcpClient client = _listener.AcceptTcpClient(); TcpClient client = _listener.AcceptTcpClient();
HttpProcessor responseProcessor = new HttpProcessor(client, _handler, _logDebugMessage, _logException); HttpProcessor responseProcessor =
Thread responseThread = new Thread(new ThreadStart(responseProcessor.Process)); new HttpProcessor(client, _handler, _logDebugMessage, _logException);
Thread responseThread = new Thread(responseProcessor.Process);
responseThread.Start(); responseThread.Start();
} }
_listener = null; _listener = null;
} }
catch (Exception) catch (Exception)
@@ -72,7 +86,7 @@ namespace VAR.HttpServer
}; };
_listener.Start(); _listener.Start();
_isActive = true; _isActive = true;
_thread = new Thread(new ThreadStart(ListenConnections)); _thread = new Thread(ListenConnections);
_thread.Start(); _thread.Start();
} }
catch (Exception ex) catch (Exception ex)
@@ -80,6 +94,7 @@ namespace VAR.HttpServer
_logException?.Invoke(ex); _logException?.Invoke(ex);
return false; return false;
} }
return true; return true;
} }
@@ -97,6 +112,7 @@ namespace VAR.HttpServer
{ {
_listener.Stop(); _listener.Stop();
} }
_thread = null; _thread = null;
} }
catch (Exception ex) catch (Exception ex)
@@ -104,6 +120,7 @@ namespace VAR.HttpServer
_logException?.Invoke(ex); _logException?.Invoke(ex);
return false; return false;
} }
return true; return true;
} }
} }

View File

@@ -4,7 +4,7 @@ using System.Text;
namespace VAR.HttpServer namespace VAR.HttpServer
{ {
public sealed class HttpUtility public static class HttpUtility
{ {
public static string UrlDecode(string str, Encoding e = null) public static string UrlDecode(string str, Encoding e = null)
{ {
@@ -19,20 +19,19 @@ namespace VAR.HttpServer
long len = str.Length; long len = str.Length;
var bytes = new List<byte>(); var bytes = new List<byte>();
int xchar;
char ch;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
ch = str[i]; char ch = str[i];
if (ch == '%' && i + 2 < len && str[i + 1] != '%') if (ch == '%' && i + 2 < len && str[i + 1] != '%')
{ {
int xChar;
if (str[i + 1] == 'u' && i + 5 < len) if (str[i + 1] == 'u' && i + 5 < len)
{ {
xchar = HexToInt(str, i + 2, 4); xChar = HexToInt(str, i + 2, 4);
if (xchar != -1) if (xChar != -1)
{ {
WriteCharBytes(bytes, (char)xchar, e); WriteCharBytes(bytes, (char)xChar, e);
i += 5; i += 5;
} }
else else
@@ -40,32 +39,24 @@ namespace VAR.HttpServer
WriteCharBytes(bytes, '%', e); WriteCharBytes(bytes, '%', e);
} }
} }
else if ((xchar = HexToInt(str, i + 1, 2)) != -1) else if ((xChar = HexToInt(str, i + 1, 2)) != -1)
{ {
WriteCharBytes(bytes, (char)xchar, e); WriteCharBytes(bytes, (char)xChar, e);
i += 2; i += 2;
} }
else else
{ {
WriteCharBytes(bytes, '%', e); WriteCharBytes(bytes, '%', e);
} }
continue; continue;
} }
if (ch == '+') WriteCharBytes(bytes, ch == '+' ? ' ' : ch, e);
{
WriteCharBytes(bytes, ' ', e);
}
else
{
WriteCharBytes(bytes, ch, e);
}
} }
byte[] buf = bytes.ToArray(); byte[] buf = bytes.ToArray();
bytes = null;
return e.GetString(buf); return e.GetString(buf);
} }
private static void WriteCharBytes(IList buf, char ch, Encoding e) private static void WriteCharBytes(IList buf, char ch, Encoding e)
@@ -115,6 +106,7 @@ namespace VAR.HttpServer
int current = HexDigitToInt((byte)c); int current = HexDigitToInt((byte)c);
if (current == -1) { return -1; } if (current == -1) { return -1; }
val = (val << 4) + current; val = (val << 4) + current;
} }
@@ -125,6 +117,7 @@ namespace VAR.HttpServer
{ {
StringBuilder sbOutput = new StringBuilder(); StringBuilder sbOutput = new StringBuilder();
if (e == null) { e = Encoding.UTF8; } if (e == null) { e = Encoding.UTF8; }
byte[] bytes = e.GetBytes(str); byte[] bytes = e.GetBytes(str);
foreach (byte c in bytes) foreach (byte c in bytes)
{ {
@@ -133,13 +126,16 @@ namespace VAR.HttpServer
sbOutput.Append('+'); sbOutput.Append('+');
continue; continue;
} }
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{ {
sbOutput.Append((char)c); sbOutput.Append((char)c);
continue; continue;
} }
sbOutput.AppendFormat("%{0:X2}", (int)c); sbOutput.AppendFormat("%{0:X2}", (int)c);
} }
return sbOutput.ToString(); return sbOutput.ToString();
} }
} }