Doing some fixup
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user