Doing some fixup

This commit is contained in:
2024-03-30 20:01:24 -05:00
parent ee57c7a3ca
commit d07cd21b98
7 changed files with 401 additions and 13 deletions
@@ -3,6 +3,7 @@ using System.IO;
using System;
using System.Net;
using System.Text;
using System.Threading;
namespace Tesses.WebServer
{
@@ -71,6 +72,17 @@ internal class SizedStream : Stream
}
public class ServerContext
{
static Mutex mtx=new Mutex();
static long _unique=0;
public static long UniqueNumber()
{
mtx.WaitOne();
long u=_unique++;
mtx.ReleaseMutex();
return u;
}
const string bad_chars = "<>?/\\\"*|:";
public static string FixFileName(string filename,bool requireAscii=false)
{
+19 -4
View File
@@ -5,9 +5,11 @@ using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HeyRed.Mime;
using Newtonsoft.Json;
namespace Tesses.WebServer
{
@@ -200,8 +202,7 @@ namespace Tesses.WebServer
}
ctx.ResponseHeaders.Add("Content-Length", (end - start + 1).ToString());
ctx.ResponseHeaders.Add("Content-Type", contentType);
ctx.WithMimeType(contentType);
await ctx.WriteHeadersAsync();
if (!ctx.Method.Equals("HEAD", StringComparison.Ordinal))
{
@@ -537,6 +538,11 @@ namespace Tesses.WebServer
}
return files;
}
public static HttpFileResponse ParseBodyWithTempDirectory(this ServerContext request)
{
DateTime dt=DateTime.Now;
return request.ParseBodyWithTempDirectory(Path.Combine(Path.GetTempPath(),$"TWSUPLOAD_{dt.ToString("yyyyMMdd_HHmmss")}_{ServerContext.UniqueNumber()}"));
}
/// <summary>
/// Parses body of the request including form and multi-part form data, allowing multiple file with same key and storing the files in a temp directory specified by the user.
/// </summary>
@@ -568,6 +574,7 @@ namespace Tesses.WebServer
}
}
public sealed class HttpFileResponseEntry
{
public HttpFileResponseEntry(string path, string filename, string fieldname, string contype)
@@ -584,8 +591,10 @@ namespace Tesses.WebServer
public string Path {get;}
public string FieldName {get;}
[JsonIgnore]
public FileInfo FileInfo => new FileInfo(Path);
[JsonIgnore]
public object PrivateData {get;set;}=null;
public Stream OpenRead()
{
@@ -606,9 +615,15 @@ namespace Tesses.WebServer
public IReadOnlyList<HttpFileResponseEntry> Files {get;}
public string Directory {get;}
public void Dispose()
{
System.IO.Directory.Delete(Directory,true);
if(System.IO.Directory.Exists(Directory))
System.IO.Directory.Delete(Directory,true);
}
~HttpFileResponse()
{
Dispose();
}
}
@@ -5,14 +5,16 @@
<PackageId>Tesses.WebServer</PackageId>
<Author>Mike Nolan</Author>
<Company>Tesses</Company>
<Version>1.0.4.2</Version>
<AssemblyVersion>1.0.4.2</AssemblyVersion>
<FileVersion>1.0.4.2</FileVersion>
<Version>1.0.4.3</Version>
<AssemblyVersion>1.0.4.3</AssemblyVersion>
<FileVersion>1.0.4.3</FileVersion>
<Description>A TCP Listener HTTP(s) Server</Description>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageTags>HTTP, WebServer, Website</PackageTags>
<RepositoryUrl>https://gitlab.tesses.net/tesses50/tesses.webserver</RepositoryUrl>
<RepositoryUrl>https://gitea.site.tesses.net/tesses50/tesses.webserver</RepositoryUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>http-icon.png</PackageIcon>
</PropertyGroup>
<ItemGroup>
@@ -20,5 +22,8 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Tesses.VirtualFileSystem.Base" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<None Include="..\http-icon.png" Pack="true" PackagePath="\" />
<None Include="..\README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>
+265 -2
View File
@@ -15,6 +15,7 @@ using System.Security.Authentication;
using System.Web;
using Tesses.VirtualFilesystem;
using System.Net.Mime;
using System.Numerics;
namespace Tesses.WebServer
{
@@ -43,6 +44,41 @@ namespace Tesses.WebServer
public static class Extensions
{
public static string GetRealRootUrl(this ServerContext ctx)
{
if(ctx.RequestHeaders.TryGetFirst("X-Forwarded-Path",out var xfwp))
{
return $"{xfwp.TrimEnd('/')}/";
}
else if(ctx.RequestHeaders.TryGetFirst("X-Forwarded-Host",out var host))
{
if(!ctx.RequestHeaders.TryGetFirst("X-Forwarded-Proto",out var proto)) proto="http";
return $"{proto}://{host}/";
}
else if(ctx.RequestHeaders.TryGetFirst("Host",out var theHost))
{
return $"http://{theHost}/";
}
return $"http://{ctx.Client}/";
}
public static string GetRealUrl(this ServerContext ctx,string url)
{
return $"{ctx.GetRealRootUrl()}{url.TrimStart('/')}";
}
public static string GetCurrentServerPath(this ServerContext ctx)
{
if(ctx.UrlPath == ctx.OriginalUrlPath) return "/";
return $"{ctx.OriginalUrlPath.Remove(ctx.OriginalUrlPath.Length-ctx.UrlPath.Length).TrimEnd('/')}/";
}
public static string GetRealUrlRelativeToCurrentServer(this ServerContext ctx, string url)
{
return ctx.GetRealUrl($"{ctx.GetCurrentServerPath()}{url.TrimStart('/')}");
}
public static ServerContext WithStatusCode(this ServerContext ctx, int statusCode)
{
ctx.StatusCode = statusCode;
return ctx;
}
public static ServerContext WithStatusCode(this ServerContext ctx, HttpStatusCode statusCode)
{
ctx.StatusCode = (int)statusCode;
@@ -116,7 +152,11 @@ namespace Tesses.WebServer
try{
EventHandler<SendEventArgs> cb= (sender,e0)=>{
if(__connected)
ctx.NetworkStream.Write($"data: {e0.Data}\n\n");
{
ctx.NetworkStream.Write($"data: {e0.Data}\n\n");
ctx.NetworkStream.Flush();
}
};
evt.EventReceived += cb;
while(ctx.Connected);
@@ -483,6 +523,229 @@ namespace Tesses.WebServer
value = default(T2);
return false;
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, object value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, int value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, short value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, long value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, Guid value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, byte value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, sbyte value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, uint value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, ushort value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, ulong value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, bool value)
{
args.Add(key,value ? "true" : "false");
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, float value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, double value)
{
args.Add(key,value.ToString());
}
public static void Add<T1>(this Dictionary<T1,List<string>> args,T1 key, decimal value)
{
args.Add(key,value.ToString());
}
public static bool TryGetFirstInt64<T1>(this Dictionary<T1,List<string>> args,T1 key, out long value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= long.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstInt32<T1>(this Dictionary<T1,List<string>> args,T1 key, out int value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= int.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstInt16<T1>(this Dictionary<T1,List<string>> args,T1 key, out short value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= short.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstInt8<T1>(this Dictionary<T1,List<string>> args,T1 key, out sbyte value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= sbyte.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool GetFirstBoolean<T1>(this Dictionary<T1,List<string>> args,T1 key)
{
if(args.TryGetFirst(key,out var value))
{
value=value.ToLower();
if(value == "off" || value == "no" || value == "false" || value == "0") return false;
return true;
}
return false;
}
public static bool TryGetFirstGuid<T1>(this Dictionary<T1,List<string>> args,T1 key, out Guid value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= Guid.TryParse(str,out var val);
value = val;
return res;
}
value=Guid.Empty;
return false;
}
public static bool TryGetFirstUInt8<T1>(this Dictionary<T1,List<string>> args,T1 key, out byte value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= byte.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstUInt16<T1>(this Dictionary<T1,List<string>> args,T1 key, out ushort value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= ushort.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstUInt64<T1>(this Dictionary<T1,List<string>> args,T1 key, out ulong value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= ulong.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstUInt32<T1>(this Dictionary<T1,List<string>> args,T1 key, out uint value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= uint.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstFloat<T1>(this Dictionary<T1,List<string>> args,T1 key, out float value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= float.TryParse(str,out var val);
value = val;
return res;
}
value=0.0f;
return false;
}
public static bool TryGetFirstBigInteger<T1>(this Dictionary<T1,List<string>> args,T1 key, out BigInteger value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= BigInteger.TryParse(str,out var val);
value = val;
return res;
}
value=0;
return false;
}
public static bool TryGetFirstDecimal<T1>(this Dictionary<T1,List<string>> args,T1 key, out decimal value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= decimal.TryParse(str,out var val);
value = val;
return res;
}
value=0.0M;
return false;
}
public static bool TryGetFirstDouble<T1>(this Dictionary<T1,List<string>> args,T1 key, out double value)
{
if(args.TryGetFirst(key,out var str))
{
bool res= double.TryParse(str,out var val);
value = val;
return res;
}
value=0.0;
return false;
}
/// <summary>
/// Add item to the Dictionary<T1,List<T2>> with specified key (will create key in dictionary if not exist)
/// </summary>
@@ -1948,7 +2211,7 @@ namespace Tesses.WebServer
}
count = Math.Min(count,this.buffer.Length-this.offset);
Array.Copy(this.buffer,this.offset,buffer,offset,count);
this.offset+=count;
return count;
}