work-in-progress
Harald Wolff 2018-07-23 12:48:06 +02:00
parent 0ce3b34093
commit 37462c7e20
9 changed files with 138 additions and 44 deletions

View File

@ -5,6 +5,7 @@ using System.Threading;
using appsrv.resources;
using System.IO;
using appsrv.test;
using System.Reflection;
namespace appsrv
{
@ -14,13 +15,14 @@ namespace appsrv
{
ApplicationServer server = new ApplicationServer();
Resource root = new DirectoryResource(new DirectoryInfo("./www"));
DirectoryResource root = new DirectoryResource(new DirectoryInfo("./www"));
StaticClassResource staticClassResource = new StaticClassResource(typeof(StaticTest), root);
root.DefaultResource = root.FindByPath("/index.html");
server.AddRoot("localhost",root);
StaticClassResource staticClassResource = new StaticClassResource(typeof(StaticTest),root);
Http http = new Http(server);
Http http = new Http(server);
http.Start();

View File

@ -11,7 +11,7 @@ namespace appsrv.http
public QueryStringParameters(String query)
{
if (query.StartsWith("?"))
if (query.StartsWith("?",StringComparison.InvariantCulture))
query = query.Substring(1);
String[] pairs = query.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -3,13 +3,13 @@ using System.IO;
using appsrv.server;
using System.Collections.Generic;
using appsrv.exceptions;
using System.Text;
namespace appsrv.resources
{
public class DirectoryResource : Resource
{
public DirectoryInfo DirectoryInfo { get; }
public bool IndexingEnabled { get; set; }
public DirectoryResource(DirectoryInfo directoryInfo)
:this(directoryInfo,null)
@ -21,34 +21,55 @@ namespace appsrv.resources
DirectoryInfo = directoryInfo;
}
public override Resource Lookup(String name){
Resource resource = base.Lookup(name);
if (resource != null)
{
return resource;
}
String newName = System.IO.Path.Combine(DirectoryInfo.FullName, name);
if (File.Exists(newName)){
if ((File.GetAttributes(newName) & FileAttributes.Directory) == FileAttributes.Directory)
{
return new DirectoryResource(new DirectoryInfo(newName), this);
} else {
return new FileResource(new FileInfo(newName), this);
}
}
throw new KeyNotFoundException(String.Format("{0} not found at {1}",name,Path));
}
public override string[] List()
{
List<String> result = new List<string>();
result.AddRange(base.List());
result.AddRange(Directory.GetFiles(DirectoryInfo.FullName));
result.AddRange(Directory.GetDirectories(DirectoryInfo.FullName));
String[] list = new string[result.Count];
for (int n = 0; n < list.Length;n++)
{
list[n] = System.IO.Path.GetFileName(result[n]);
}
return list;
}
public override void Hit(Stack<string> requestPath, HttpRequest request)
{
if (requestPath.Count > 0)
{
String nextResourceName = requestPath.Pop();
Resource nextResource = Lookup(nextResourceName);
DirectoryInfo[] directoryInfos = DirectoryInfo.GetDirectories(nextResourceName);
if (directoryInfos.Length == 1){
DirectoryResource directoryResource = new DirectoryResource(directoryInfos[0],this);
directoryResource.Request(requestPath, request);
} else {
FileInfo[] fileInfos = DirectoryInfo.GetFiles(nextResourceName);
if (fileInfos.Length == 1){
FileResource fileResource = new FileResource(fileInfos[0],this);
fileResource.Request(requestPath, request);
} else {
throw new ResourceNotFoundException(Path, nextResourceName);
}
}
nextResource.Request(requestPath, request);
} else {
if (IndexingEnabled){
// ToDo: Create index...
} else {
base.Hit(requestPath, request);
}
base.Hit(requestPath, request);
}
}

View File

@ -4,16 +4,21 @@ using System.Collections.Generic;
using System.Dynamic;
using appsrv.exceptions;
using System.Linq;
using System.Text;
namespace appsrv.resources
{
public abstract class Resource
{
public Resource Container { get; }
public String Name { get; }
public Resource DefaultResource { get; set; }
public bool IndexingEnabled { get; set; }
Dictionary<String, Resource> resources = new Dictionary<string, Resource>();
public Resource(String name)
{
Name = name;
@ -26,6 +31,17 @@ namespace appsrv.resources
container.Add(this);
}
public virtual Resource Lookup(String name)
{
if (resources.ContainsKey(name))
return resources[name];
return null;
}
public virtual String[] List()
{
return resources.Keys.ToArray();
}
protected virtual void Add(Resource resource){
resources.Add(resource.Name, resource);
}
@ -35,16 +51,16 @@ namespace appsrv.resources
}
}
public bool Contains(String resName)
public virtual bool Contains(String resName)
{
return resources.ContainsKey(resName);
return Lookup(resName) != null;
}
public bool Contains(Resource resource)
public virtual bool Contains(Resource resource)
{
return resources.ContainsValue(resource);
return (resource.Container == this) && (Lookup(resource.Name) == resource);
}
public ISet<Resource> Resources { get => new HashSet<Resource>(resources.Values); }
public virtual ISet<Resource> Resources => new HashSet<Resource>(resources.Values);
public Resource Root {
get {
@ -76,7 +92,7 @@ namespace appsrv.resources
public virtual Resource this[string name]{
get => resources[name];
get => Lookup(name);
}
public virtual void Request(Stack<String> requestPath, HttpRequest request)
@ -85,11 +101,18 @@ namespace appsrv.resources
{
if ((requestPath.Count > 0) && (Contains(requestPath.Peek())))
{
this[requestPath.Pop()].Request(requestPath, request);
Lookup(requestPath.Pop()).Request(requestPath, request);
}
else
{
Hit(requestPath, request);
if ((requestPath.Count == 0) && (DefaultResource != null))
{
DefaultResource.Request(requestPath, request);
}
else
{
Hit(requestPath, request);
}
}
}
catch (ApplicationServerException ase)
@ -102,7 +125,11 @@ namespace appsrv.resources
if (requestPath.Count > 0){
throw new ResourceNotFoundException(Path, requestPath.Peek());
} else {
throw new ApplicationServerException("unimplemented resource has been hit");
if (IndexingEnabled){
CreateIndex(request);
} else {
throw new ApplicationServerException("unimplemented resource has been hit");
}
}
}
@ -136,6 +163,24 @@ namespace appsrv.resources
Console.WriteLine("ASE: " + ase.ToString());
}
protected void CreateIndex(HttpRequest request){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("<html><head><title>{0}</title></head>", Path);
stringBuilder.AppendFormat("<body><h1>Index of {0}</h1>", Path);
foreach (String name in List())
{
String p = Path;
if (p.Equals("/"))
p = "";
stringBuilder.AppendFormat("<a href=\"{0}/{1}\">{1}</a><br/>", p, name);
}
stringBuilder.Append("</body></html>");
request.SetResponseHeader("Content-Type", "text/html");
request.ResponseWriter.Write(stringBuilder.ToString());
}
}
}

View File

@ -55,8 +55,13 @@ namespace appsrv.resources
for (int n = 0; n < parameters.Length;n++)
{
ParameterInfo parameterInfo = parameters[n];
object pvalue = request.Query[parameterInfo.Name];
p[n] = Convert.ChangeType(pvalue, parameterInfo.ParameterType );
if (request.Query.ContainsKey(parameterInfo.Name)){
p[n] = Convert.ChangeType(request.Query[parameterInfo.Name], parameterInfo.ParameterType);
} else if (parameterInfo.IsOptional){
p[n] = System.Type.Missing;
} else {
throw new ArgumentException("");
}
}
return p;
@ -74,9 +79,14 @@ namespace appsrv.resources
}
}
private void SerializePlain(HttpRequest request,object result){
private void SerializePlain(HttpRequest request, object result)
{
request.SetResponseHeader("Content-Type", "text/plain");
byte[] plain = Encoding.UTF8.GetBytes(result.ToString());
byte[] plain;
if (result == null)
plain = new byte[0];
else
plain = Encoding.UTF8.GetBytes(result.ToString());
request.ResponseStream.Write(plain, 0, plain.Length);
}

View File

@ -115,12 +115,17 @@ namespace appsrv.server
{
if (this.responseWriter == null)
{
this.responseWriter = new StreamWriter(this.responseStream);
this.responseWriter = new StreamWriter(ResponseStream);
}
return this.responseWriter;
}
}
public void Flush()
{
if (responseWriter != null)
responseWriter.Flush();
}
@ -192,6 +197,8 @@ namespace appsrv.server
private void SendResponse()
{
Flush();
using (StreamWriter writer = new StreamWriter(this.stream))
{
ResponseStream.Position = 0;

View File

@ -13,9 +13,11 @@ namespace appsrv.test
}
[WebCallable]
public static void Debug()
public static String Debug(String debugMessage = null)
{
Console.WriteLine("StaticTest.Debug() has been called");
String debugLine = String.Format("StaticTest.Debug({0}) has been called", debugMessage);
Console.WriteLine(debugLine);
return debugLine;
}
}
}

View File

@ -5,5 +5,12 @@
<body>
<h1>appsrv test page</h1>
<p>A paragraph to see the file is displayed.</p>
<form action="/StaticTest/Debug">
Debug Message:
<input type="text" name="debugMessage" value=""/>
<input type="submit" value="Senden"/>
</form>
</body>
</html>