Compare commits

...

3 Commits

Author SHA1 Message Date
Harald Wolff 7dffea6bf5 Add simple test iteration HttpRequest.Session to frame.html 2019-02-26 22:01:13 +01:00
Harald Wolff b7448e0766 WIP 2019-02-14 16:44:51 +01:00
Harald Wolff 4ebf06add5 Initial Version of simple2 Branch 2019-02-14 09:13:38 +01:00
22 changed files with 380 additions and 841 deletions

View File

@ -1,32 +1,64 @@
using System;
using appsrv.server;
using appsrv.protocol;
using System.Threading;
using appsrv.resources;
using System.IO;
using appsrv.test;
using System.Net;
using ln.http;
using System.Collections.Generic;
using System.Web.UI;
using ln.templates;
using ln.http.resources;
namespace appsrv
namespace httpsrv
{
class MainClass
class Person
{
public int Id { get; private set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public DateTime BirthDay { get; set; }
}
class Persons
{
public Person this[string name]
{
get { return null; }
}
}
class MainClass
{
public static void Main(string[] args)
{
ApplicationServer server = new ApplicationServer();
HTTPServer httpServer = new HTTPServer();
httpServer.AddEndpoint(new IPEndPoint(IPAddress.Loopback, 8080));
Resource root = new DirectoryResource(new DirectoryInfo("./www"));
server.AddRoot("localhost",root);
ResourceApplication application = new ResourceApplication();
StaticClassResource staticClassResource = new StaticClassResource(typeof(StaticTest),root);
DirectoryResource dr = new DirectoryResource(application.RootResource, "www");
dr.ResourceTypeHook = (DirectoryResource directoryResource, FileInfo fileInfo) => {
if (fileInfo.Extension == ".html")
return new TemplateResource(directoryResource, fileInfo.FullName);
return null;
};
application.RootResource.DefaultResource = dr;
httpServer.DefaultApplication = application;
httpServer.Start();
while (true)
{
Thread.Sleep(1000);
}
Http http = new Http(server);
http.Start();
Thread.Sleep(10000);
http.Stop();
}
}

View File

@ -7,7 +7,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>appsrv</RootNamespace>
<AssemblyName>appsrv</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
@ -30,38 +30,25 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Web" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="connector\Http.cs" />
<Compile Include="server\ApplicationServer.cs" />
<Compile Include="connector\Connector.cs" />
<Compile Include="server\Application.cs" />
<Compile Include="server\HttpRequest.cs" />
<Compile Include="exceptions\IllegalRequestException.cs" />
<Compile Include="resources\Resource.cs" />
<Compile Include="resources\FileResource.cs" />
<Compile Include="resources\DirectoryResource.cs" />
<Compile Include="exceptions\ApplicationServerException.cs" />
<Compile Include="exceptions\ResourceNotFoundException.cs" />
<Compile Include="mime\MimeHelper.cs" />
<Compile Include="http\HttpStatusCodes.cs" />
<Compile Include="resources\ResourceLink.cs" />
<Compile Include="resources\StaticClassResource.cs" />
<Compile Include="attributes\WebCallable.cs" />
<Compile Include="test\StaticTest.cs" />
<Compile Include="http\QueryStringParameters.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="connector\" />
<Folder Include="server\" />
<Folder Include="exceptions\" />
<Folder Include="resources\" />
<Folder Include="www\" />
<Folder Include="www\gfx\" />
<Folder Include="mime\" />
<Folder Include="http\" />
<Folder Include="attributes\" />
<Folder Include="test\" />
</ItemGroup>
@ -69,6 +56,23 @@
<None Include="www\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="www\frame.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.http\ln.http.csproj">
<Project>{CEEEEB41-3059-46A2-A871-2ADE22C013D9}</Project>
<Name>ln.http</Name>
</ProjectReference>
<ProjectReference Include="..\ln.templates\ln.templates.csproj">
<Project>{AD0267BB-F08C-4BE1-A88D-010D49041761}</Project>
<Name>ln.templates</Name>
</ProjectReference>
<ProjectReference Include="..\ln.http.resources\ln.http.resources.csproj">
<Project>{F9086FE4-8925-42FF-A59C-607341604293}</Project>
<Name>ln.http.resources</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>

View File

@ -1,5 +1,5 @@
using System;
namespace appsrv.attributes
namespace ln.http.attributes
{
public enum Serialization {
PLAIN,

View File

@ -1,18 +0,0 @@
using System;
using appsrv.server;
namespace appsrv.connector
{
public abstract class Connector
{
public ApplicationServer ApplicationServer { get; private set; }
public Connector(ApplicationServer applicationServer)
{
this.ApplicationServer = applicationServer;
}
public abstract void Start();
public abstract void Stop();
}
}

View File

@ -1,84 +0,0 @@
using System;
using System.Net;
using System.Net.Sockets;
using appsrv.connector;
using appsrv.server;
using System.Threading;
namespace appsrv.protocol
{
public class Http : Connector
{
public static int backlog = 5;
public static int defaultPort = 8080;
public static bool exclusivePortListener = false;
IPEndPoint endPoint;
TcpListener tcpListener;
Thread tAccept;
public Http(ApplicationServer appServer)
:this(appServer,new IPEndPoint(IPAddress.Any, defaultPort))
{
}
public Http(ApplicationServer appServer,IPEndPoint endPoint)
: base(appServer)
{
this.endPoint = endPoint;
this.tcpListener = new TcpListener(this.endPoint);
this.tcpListener.ExclusiveAddressUse = exclusivePortListener;
}
public override void Start()
{
if (
(tAccept == null) ||
(!tAccept.IsAlive))
{
this.tcpListener.Start(backlog);
tAccept = new Thread(new ThreadStart(() => acceptRequests()));
tAccept.Start();
}
}
public override void Stop()
{
this.tcpListener.Stop();
}
private void acceptRequests(){
try
{
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
try
{
HttpRequest request = new HttpRequest(this.ApplicationServer, client);
Console.WriteLine("new request: {0}",request);
Thread t = new Thread(() => request.Handle());
t.Start();
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e);
}
}
} catch (SocketException e){
Console.WriteLine("Http connector interupted");
}
}
}
}

View File

@ -1,28 +0,0 @@
using System;
namespace appsrv.exceptions
{
public class ApplicationServerException : Exception
{
public int StatusCode { get; } = 500;
public ApplicationServerException(String message)
: base(message)
{
}
public ApplicationServerException(String message, Exception innerException)
: base(message, innerException)
{
}
public ApplicationServerException(int statusCode,String message)
: base(message)
{
StatusCode = statusCode;
}
public ApplicationServerException(int statusCode,String message, Exception innerException)
: base(message, innerException)
{
StatusCode = statusCode;
}
}
}

View File

@ -1,11 +0,0 @@
using System;
namespace appsrv.exceptions
{
public class IllegalRequestException : Exception
{
public IllegalRequestException(String requestLine)
:base(requestLine)
{
}
}
}

View File

@ -1,11 +0,0 @@
using System;
namespace appsrv.exceptions
{
public class ResourceNotFoundException : ApplicationServerException
{
public ResourceNotFoundException(String resourcePath, String nextResource)
: base(404, String.Format("Could not find resource \"{0}\" within \"{1}\"", nextResource, resourcePath))
{
}
}
}

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
namespace appsrv.http
{
public class HttpStatusCodes
{
static Dictionary<int, string> statusMessages = new Dictionary<int, string>()
{
{ 200, "Ok" },
{ 403, "Access denied" },
{ 404, "Not Found" }
};
public static String GetStatusMessage(int code){
if (statusMessages.ContainsKey(code))
return statusMessages[code];
return "Unknown Status";
}
}
}

View File

@ -1,65 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace appsrv.http
{
public class QueryStringParameters : IDictionary<String,String>
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
public QueryStringParameters(String query)
{
if (query.StartsWith("?"))
query = query.Substring(1);
String[] pairs = query.Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
foreach (String pair in pairs)
{
String[] kv = pair.Split(new char[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries);
string key = Uri.UnescapeDataString(kv[0].Replace('+',' '));
string value = kv.Length == 2 ? Uri.UnescapeDataString(kv[1].Replace('+',' ')) : "";
if (!key.Equals(String.Empty)){
parameters[key] = value;
}
}
}
public string this[string key] {
get => parameters[key];
set => throw new NotImplementedException(); }
public ICollection<string> Keys => parameters.Keys;
public ICollection<string> Values => parameters.Values;
public int Count => parameters.Count;
public bool IsReadOnly => true;
public void Add(string key, string value) => throw new NotImplementedException();
public void Add(KeyValuePair<string, string> item) => throw new NotImplementedException();
public void Clear() => throw new NotImplementedException();
public bool Remove(string key) => throw new NotImplementedException();
public bool Remove(KeyValuePair<string, string> item) => throw new NotImplementedException();
public bool Contains(KeyValuePair<string, string> item) => parameters.Contains(item);
public bool ContainsKey(string key) => parameters.ContainsKey(key);
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) => ((IDictionary<string, string>)parameters).CopyTo(array, arrayIndex);
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => parameters.GetEnumerator();
public bool TryGetValue(string key, out string value) => parameters.TryGetValue(key, out value);
IEnumerator IEnumerable.GetEnumerator() => parameters.GetEnumerator();
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("[Query");
foreach (String key in parameters.Keys){
stringBuilder.AppendFormat(" {0}={1}", key, parameters[key]);
}
stringBuilder.Append("]");
return stringBuilder.ToString();
}
}
}

View File

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
namespace appsrv.mime
namespace ln.http.mime
{
public static class MimeHelper
{

View File

@ -1,56 +1,55 @@
using System;
using System.IO;
using appsrv.server;
using System.Collections.Generic;
using appsrv.exceptions;
using ln.http.exceptions;
namespace appsrv.resources
namespace ln.http.resources
{
public class DirectoryResource : Resource
{
public DirectoryInfo DirectoryInfo { get; }
public bool IndexingEnabled { get; set; }
//public class DirectoryResource : Resource
//{
// public DirectoryInfo DirectoryInfo { get; }
// public bool IndexingEnabled { get; set; }
public DirectoryResource(DirectoryInfo directoryInfo)
:this(directoryInfo,null)
{
}
public DirectoryResource(DirectoryInfo directoryInfo,Resource container)
:base(directoryInfo.Name,container)
{
DirectoryInfo = directoryInfo;
}
// public DirectoryResource(DirectoryInfo directoryInfo)
// :this(directoryInfo,null)
// {
// }
// public DirectoryResource(DirectoryInfo directoryInfo,Resource container)
// :base(directoryInfo.Name,container)
// {
// DirectoryInfo = directoryInfo;
// }
public override void Hit(Stack<string> requestPath, HttpRequest request)
{
if (requestPath.Count > 0)
{
String nextResourceName = requestPath.Pop();
// public override void Hit(Stack<string> requestPath, HttpRequest request)
// {
// if (requestPath.Count > 0)
// {
// String nextResourceName = requestPath.Pop();
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);
}
}
// 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);
// }
// }
} else {
if (IndexingEnabled){
// } else {
// if (IndexingEnabled){
// ToDo: Create index...
// // ToDo: Create index...
} else {
base.Hit(requestPath, request);
}
}
}
// } else {
// base.Hit(requestPath, request);
// }
// }
// }
}
//}
}

View File

@ -1,38 +1,37 @@
using System;
using appsrv.server;
using System.IO;
using System.Collections.Generic;
using appsrv.exceptions;
using appsrv.mime;
using ln.http.exceptions;
using ln.http.mime;
namespace appsrv.resources
namespace ln.http.resources
{
public class FileResource : Resource
{
public FileInfo FileInfo { get; }
public bool DiscardRequestPath { get; set; }
//public class FileResource : Resource
//{
// public FileInfo FileInfo { get; }
// public bool DiscardRequestPath { get; set; }
public FileResource(FileInfo fileInfo,Resource container)
:base(fileInfo.Name,container)
{
FileInfo = fileInfo;
}
// public FileResource(FileInfo fileInfo,Resource container)
// :base(fileInfo.Name,container)
// {
// FileInfo = fileInfo;
// }
public override void Hit(Stack<string> requestPath, HttpRequest request)
{
if ((requestPath.Count > 0) && !DiscardRequestPath){
throw new ApplicationServerException(String.Format("No resources below {0}",Path));
} else {
// //public override void Hit(Stack<string> requestPath, HttpRequest request)
// //{
// // if ((requestPath.Count > 0) && !DiscardRequestPath){
// // throw new ApplicationServerException(String.Format("No resources below {0}",Path));
// // } else {
request.SetResponseHeader("Content-Type", MimeHelper.GuessMIMEFromFilename(FileInfo.Name));
// // request.SetResponseHeader("Content-Type", MimeHelper.GuessMIMEFromFilename(FileInfo.Name));
using (FileStream fileStream = new FileStream(FileInfo.FullName,FileMode.Open))
{
fileStream.CopyTo(request.ResponseStream);
fileStream.Close();
}
}
}
// // using (FileStream fileStream = new FileStream(FileInfo.FullName,FileMode.Open))
// // {
// // fileStream.CopyTo(request.ResponseStream);
// // fileStream.Close();
// // }
// // }
// //}
}
//}
}

View File

@ -1,141 +1,142 @@
using System;
using appsrv.server;
using ln.http;
using System.Collections.Generic;
using System.Dynamic;
using appsrv.exceptions;
using System.Linq;
namespace appsrv.resources
namespace ln.http.resources
{
public abstract class Resource
{
public Resource Container { get; }
public String Name { get; }
//public abstract class Resource
//{
// public Resource Container { get; }
// public String Name { get; }
Dictionary<String, Resource> resources = new Dictionary<string, Resource>();
// Dictionary<String, Resource> resources = new Dictionary<string, Resource>();
public Resource(String name)
{
Name = name;
}
public Resource(String name,Resource container)
{
Name = name;
Container = container;
if (container != null)
container.Add(this);
}
// public Resource(String name)
// {
// Name = name;
// }
// public Resource(String name,Resource container)
// {
// Name = name;
// Container = container;
// if (container != null)
// container.Add(this);
// }
protected virtual void Add(Resource resource){
resources.Add(resource.Name, resource);
}
protected virtual void Remove(Resource resource){
if (resources.ContainsValue(resource)){
resources.Remove(resource.Name);
}
}
// protected virtual void Add(Resource resource){
// resources.Add(resource.Name, resource);
// }
// protected virtual void Remove(Resource resource){
// if (resources.ContainsValue(resource)){
// resources.Remove(resource.Name);
// }
// }
public bool Contains(String resName)
{
return resources.ContainsKey(resName);
}
public bool Contains(Resource resource)
{
return resources.ContainsValue(resource);
}
// public bool Contains(String resName)
// {
// return resources.ContainsKey(resName);
// }
// public bool Contains(Resource resource)
// {
// return resources.ContainsValue(resource);
// }
public ISet<Resource> Resources { get => new HashSet<Resource>(resources.Values); }
// public ISet<Resource> Resources { get => new HashSet<Resource>(resources.Values); }
public Resource Root {
get {
if (Container == null)
return this;
else
return Container.Root;
}
}
// public Resource Root {
// get {
// if (Container == null)
// return this;
// else
// return Container.Root;
// }
// }
public IList<String> PathList {
get {
if (Container != null)
{
IList<String> pl = Container.PathList;
pl.Add(Name);
return pl;
} else {
return new List<String>();
}
}
}
// public IList<String> PathList {
// get {
// if (Container != null)
// {
// IList<String> pl = Container.PathList;
// pl.Add(Name);
// return pl;
// } else {
// return new List<String>();
// }
// }
// }
public String Path {
get {
return String.Format("/{0}",String.Join("/",PathList));
}
}
// public String Path {
// get {
// return String.Format("/{0}",String.Join("/",PathList));
// }
// }
public virtual Resource this[string name]{
get => resources[name];
}
// public virtual Resource this[string name]{
// get => resources[name];
// }
public virtual void Request(Stack<String> requestPath, HttpRequest request)
{
try
{
if ((requestPath.Count > 0) && (Contains(requestPath.Peek())))
{
this[requestPath.Pop()].Request(requestPath, request);
}
else
{
Hit(requestPath, request);
}
}
catch (ApplicationServerException ase)
{
HandleException(ase);
}
}
// public virtual void Request(Stack<String> requestPath, HttpRequest request)
// {
// try
// {
// if ((requestPath.Count > 0) && (Contains(requestPath.Peek())))
// {
// this[requestPath.Pop()].Request(requestPath, request);
// }
// else
// {
// Hit(requestPath, request);
// }
// }
// catch (ApplicationServerException ase)
// {
// HandleException(ase);
// }
// }
public virtual void Hit(Stack<String> requestPath, HttpRequest request){
if (requestPath.Count > 0){
throw new ResourceNotFoundException(Path, requestPath.Peek());
} else {
throw new ApplicationServerException("unimplemented resource has been hit");
}
}
// public virtual void Hit(Stack<String> requestPath, HttpRequest request){
// if (requestPath.Count > 0){
// throw new ResourceNotFoundException(Path, requestPath.Peek());
// } else {
// throw new ApplicationServerException("unimplemented resource has been hit");
// }
// }
public Resource FindByPath(String path)
{
String[] pathTokens = path.Split(new char[]{'/'},StringSplitOptions.RemoveEmptyEntries);
if (path[0] == '/')
return Root.FindByPath(pathTokens);
else
return FindByPath(pathTokens);
}
public Resource FindByPath(IEnumerable<String> path)
{
return FindByPath(path.GetEnumerator());
}
public Resource FindByPath(IEnumerator<String> path)
{
if (path.MoveNext())
{
return this[path.Current].FindByPath(path);
}
else
{
return this;
}
}
// public Resource FindByPath(String path)
// {
// String[] pathTokens = path.Split(new char[]{'/'},StringSplitOptions.RemoveEmptyEntries);
// if (path[0] == '/')
// return Root.FindByPath(pathTokens);
// else
// return FindByPath(pathTokens);
// }
// public Resource FindByPath(IEnumerable<String> path)
// {
// return FindByPath(path.GetEnumerator());
// }
// public Resource FindByPath(IEnumerator<String> path)
// {
// if (path.MoveNext())
// {
// return this[path.Current].FindByPath(path);
// }
// else
// {
// return this;
// }
// }
protected void HandleException(ApplicationServerException ase){
Console.WriteLine("ASE: " + ase.ToString());
}
// protected void HandleException(ApplicationServerException ase){
// Console.WriteLine("ASE: " + ase.ToString());
// }
}
//}
}

View File

@ -1,28 +1,27 @@
using System;
using System.Collections.Generic;
using appsrv.server;
namespace appsrv.resources
namespace ln.http.resources
{
public class ResourceLink : Resource
{
Resource Target { get; }
//public class ResourceLink : Resource
//{
// Resource Target { get; }
public ResourceLink(String name,Resource container,Resource target)
:base(name,container)
{
Target = target;
}
// public ResourceLink(String name,Resource container,Resource target)
// :base(name,container)
// {
// Target = target;
// }
protected override void Add(Resource resource)
{
throw new ArgumentOutOfRangeException("This resource can't have children");
}
// protected override void Add(Resource resource)
// {
// throw new ArgumentOutOfRangeException("This resource can't have children");
// }
public override void Request(Stack<string> requestPath, HttpRequest request)
{
Target.Request(requestPath, request);
}
// public override void Request(Stack<string> requestPath, HttpRequest request)
// {
// Target.Request(requestPath, request);
// }
}
//}
}

View File

@ -1,92 +1,91 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using appsrv.attributes;
using appsrv.server;
using ln.http.attributes;
using System.Text;
namespace appsrv.resources
namespace ln.http.resources
{
public class StaticClassResource : Resource
{
Type Type { get; }
//public class StaticClassResource : Resource
//{
// Type Type { get; }
Dictionary<string, FieldInfo> callableFields = new Dictionary<string, FieldInfo>();
// Dictionary<string, FieldInfo> callableFields = new Dictionary<string, FieldInfo>();
public StaticClassResource(Type type,Resource container)
:base(type.Name,container)
{
Type = type;
// public StaticClassResource(Type type,Resource container)
// :base(type.Name,container)
// {
// Type = type;
foreach (MethodInfo methodInfo in Type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)){
WebCallable webCallable = methodInfo.GetCustomAttribute<WebCallable>();
if (webCallable != null){
new CallableMethodResource(methodInfo, this);
}
}
// foreach (MethodInfo methodInfo in Type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)){
// WebCallable webCallable = methodInfo.GetCustomAttribute<WebCallable>();
// if (webCallable != null){
// new CallableMethodResource(methodInfo, this);
// }
// }
}
// }
class CallableMethodResource : Resource
{
MethodInfo MethodInfo { get; }
WebCallable WebCallable { get; }
// class CallableMethodResource : Resource
// {
// MethodInfo MethodInfo { get; }
// WebCallable WebCallable { get; }
public CallableMethodResource(MethodInfo methodInfo,Resource container)
:base(
methodInfo.GetCustomAttribute<WebCallable>() != null ?
(methodInfo.GetCustomAttribute<WebCallable>().Name != null) ? methodInfo.GetCustomAttribute<WebCallable>().Name : methodInfo.Name
:methodInfo.Name,
container
)
{
MethodInfo = methodInfo;
WebCallable = methodInfo.GetCustomAttribute<WebCallable>();
}
// public CallableMethodResource(MethodInfo methodInfo,Resource container)
// :base(
// methodInfo.GetCustomAttribute<WebCallable>() != null ?
// (methodInfo.GetCustomAttribute<WebCallable>().Name != null) ? methodInfo.GetCustomAttribute<WebCallable>().Name : methodInfo.Name
// :methodInfo.Name,
// container
// )
// {
// MethodInfo = methodInfo;
// WebCallable = methodInfo.GetCustomAttribute<WebCallable>();
// }
private object[] ReadParameters(HttpRequest request)
{
ParameterInfo[] parameters = MethodInfo.GetParameters();
object[] p = new object[ parameters.Length ];
// private object[] ReadParameters(HttpRequest request)
// {
// ParameterInfo[] parameters = MethodInfo.GetParameters();
// object[] p = new object[ parameters.Length ];
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 );
}
// 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 );
// }
return p;
}
// return p;
// }
private void SerializeResult(HttpRequest request,object result){
switch (WebCallable.Serialization){
case Serialization.PLAIN:
SerializePlain(request, result);
break;
case Serialization.JSON:
break;
case Serialization.XML:
break;
}
}
// //private void SerializeResult(HttpRequest request,object result){
// // switch (WebCallable.Serialization){
// // case Serialization.PLAIN:
// // SerializePlain(request, result);
// // break;
// // case Serialization.JSON:
// // break;
// // case Serialization.XML:
// // break;
// // }
// //}
private void SerializePlain(HttpRequest request,object result){
request.SetResponseHeader("Content-Type", "text/plain");
byte[] plain = Encoding.UTF8.GetBytes(result.ToString());
request.ResponseStream.Write(plain, 0, plain.Length);
}
// //private void SerializePlain(HttpRequest request,object result){
// // request.SetResponseHeader("Content-Type", "text/plain");
// // byte[] plain = Encoding.UTF8.GetBytes(result.ToString());
// // request.ResponseStream.Write(plain, 0, plain.Length);
// //}
public override void Hit(Stack<string> requestPath, HttpRequest request)
{
object[] p = ReadParameters(request);
object result = MethodInfo.Invoke(null, p);
SerializeResult(request, result);
}
// //public override void Hit(Stack<string> requestPath, HttpRequest request)
// //{
// // object[] p = ReadParameters(request);
// // object result = MethodInfo.Invoke(null, p);
// // SerializeResult(request, result);
// //}
}
}
// }
//}
}

View File

@ -1,13 +0,0 @@
using System;
namespace appsrv.server
{
public class Application
{
public ApplicationServer ApplicationServer { get; private set; }
public Application(ApplicationServer applicationServer)
{
this.ApplicationServer = applicationServer;
}
}
}

View File

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using appsrv.resources;
using System.Linq;
namespace appsrv.server
{
public class ApplicationServer
{
public Resource DefaultRoot { get; set; }
Dictionary<String, Resource> roots = new Dictionary<string, Resource>();
public ApplicationServer()
{
}
public void AddRoot(String name,Resource rootResource){
roots.Add(name, rootResource);
if (DefaultRoot == null){
DefaultRoot = rootResource;
}
}
public Resource FindRoot(String rootName)
{
if (roots.ContainsKey(rootName))
return roots[rootName];
return DefaultRoot;
}
public void HandleRequest(HttpRequest request){
Resource rootResource = FindRoot(request.Hostname);
Stack<String> requestPath = new Stack<string>(request.URI.AbsolutePath.Split(new char[] { '/' },StringSplitOptions.RemoveEmptyEntries).Reverse());
rootResource.Request(requestPath, request);
}
}
}

View File

@ -1,229 +0,0 @@
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using appsrv.exceptions;
using appsrv.http;
namespace appsrv.server
{
public class HttpRequest
{
private Stream stream;
private StreamReader streamReader;
private List<HttpRequest> currentRequests = new List<HttpRequest>();
private MemoryStream responseStream;
private StreamWriter responseWriter;
Dictionary<String, String> requestHeaders = new Dictionary<string, string>();
Dictionary<String, String> responseHeaders = new Dictionary<string, string>();
public EndPoint Client { get; private set; }
public ApplicationServer ApplicationServer { get; private set; }
public Uri URI { get; private set; }
public String Method { get; private set; }
public String RequestURL { get; private set; }
public String Protocol { get; private set; }
public String Hostname { get; private set; }
public int Port { get; private set; }
public QueryStringParameters Query { get; private set; }
public int StatusCode { get; set; } = 200;
public HttpRequest(ApplicationServer applicationServer, TcpClient client)
{
this.ApplicationServer = applicationServer;
this.Client = client.Client.RemoteEndPoint;
this.stream = client.GetStream();
this.streamReader = new StreamReader(this.stream);
String rLine = this.streamReader.ReadLine();
String[] rTokens = SplitWhitespace(
rLine
);
Console.WriteLine("Tokens: {0}", rTokens);
if (rTokens.Length != 3){
throw new IllegalRequestException(rLine);
}
this.Method = rTokens[0];
this.RequestURL = rTokens[1];
this.Protocol = rTokens[2];
}
public override string ToString()
{
return string.Format("[HttpRequest: Client={0}, ApplicationServer={1}, Hostname={6} Port={7} URI={2}, Method={3}, RequestURL={4}, Protocol={5} Query={8}]", Client, ApplicationServer, URI, Method, RequestURL, Protocol, Hostname, Port,Query);
}
public String GetRequestHeader(String name, String def = "")
{
name = name.ToLowerInvariant();
if (requestHeaders.ContainsKey(name))
return requestHeaders[name];
return def;
}
public String GetResponseHeader(String name, String def = "")
{
name = name.ToLowerInvariant();
if (responseHeaders.ContainsKey(name))
return responseHeaders[name];
return def;
}
public void SetResponseHeader(String name,String value){
name = name.ToLowerInvariant();
if (value == null)
{
this.responseHeaders.Remove(name);
}
else
{
this.responseHeaders[name] = value;
}
}
public Stream ResponseStream
{
get {
if (responseStream == null)
responseStream = new MemoryStream();
return responseStream;
}
}
public TextWriter ResponseWriter
{
get
{
if (this.responseWriter == null)
{
this.responseWriter = new StreamWriter(this.responseStream);
}
return this.responseWriter;
}
}
private String[] SplitWhitespace(String line){
LinkedList<String> tokens = new LinkedList<string>();
StringBuilder sb = new StringBuilder();
for (int n = 0; n < line.Length;)
{
for (; n < line.Length && !Char.IsWhiteSpace(line[n]); n++)
sb.Append(line[n]);
tokens.AddLast(sb.ToString());
sb.Clear();
for (; n < line.Length && Char.IsWhiteSpace(line[n]); n++) {}
}
return tokens.ToArray();
}
private void ReadHttpHeaders(){
String headerLine = this.streamReader.ReadLine();
String hName = null;
while (!headerLine.Equals(String.Empty)){
if (Char.IsWhiteSpace(headerLine[0]) && hName != null)
{
requestHeaders[hName] = requestHeaders[hName] + "," + headerLine.Trim();
} else {
String[] split = headerLine.Split(new char[] { ':' }, 2);
if (split.Length != 2){
throw new IllegalRequestException("malformed header");
}
hName = split[0].ToLowerInvariant();
requestHeaders[hName] = split[1];
}
headerLine = this.streamReader.ReadLine();
}
foreach (String hname in requestHeaders.Keys.ToArray()){
requestHeaders[hname] = requestHeaders[hname].Trim();
}
}
private void InterpretRequestHeaders()
{
String host = GetRequestHeader("host");
String[] hostTokens = host.Split(':');
Hostname = hostTokens[0];
if (hostTokens.Length > 1){
Port = int.Parse(hostTokens[1]);
}
URI = new Uri(String.Format("http://{0}:{1}/{2}", Hostname, Port, RequestURL));
Query = new QueryStringParameters(URI.Query);
}
private void SendResponse()
{
using (StreamWriter writer = new StreamWriter(this.stream))
{
ResponseStream.Position = 0;
SetResponseHeader("Content-Length", responseStream.Length.ToString());
writer.WriteLine("{0} {1} {2}", Protocol, StatusCode, HttpStatusCodes.GetStatusMessage(StatusCode));
foreach (String rhName in responseHeaders.Keys){
writer.WriteLine("{0}: {1}", rhName, responseHeaders[rhName]);
}
writer.WriteLine();
writer.Flush();
responseStream.CopyTo(this.stream);
}
}
public void Handle(){
this.ReadHttpHeaders();
this.InterpretRequestHeaders();
Console.WriteLine("Request Handled: {0}",this);
foreach (String key in this.requestHeaders.Keys){
Console.WriteLine("HH: {0} = {1}",key,this.requestHeaders[key]);
}
ApplicationServer.HandleRequest(this);
SendResponse();
this.streamReader.Close();
this.stream.Close();
}
}
}

View File

@ -1,6 +1,6 @@
using System;
using appsrv.attributes;
namespace appsrv.test
using ln.http.attributes;
namespace ln.http.test
{
public class StaticTest

30
www/frame.html 100644
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>appsrv test page</title>
</head>
<body>
<h1>I am the frame!</h1>
<p><%=__frame__%></p>
<div>
<h3>request Headers:</h3>
<table>
<%iterate name request.RequestHeaderNames%>
<tr>
<td><i><%=name%>:</i></td>
<td><%=request.GetRequestHeader(name)%></td>
</tr> <%end%>
</table>
<h3>session variables (SID: <%=request.Session.SessionID%>)
<table>
<%iterate name request.Session.ElementNames%>
<tr>
<td><i><%=name%>:</i></td>
<td><%=request.Session[name]%></td>
</tr>
<%end%>
</table>
</div>
</body>
</html>

View File

@ -1,9 +1,7 @@
<html>
<head>
<title>appsrv test page</title>
</head>
<body>
<h1>appsrv test page</h1>
<p>A paragraph to see the file is displayed.</p>
</body>
</html>
<%frame "/frame.html"%>
<h1>appsrv test page</h1>
<p>A paragraph to see the file is displayed.</p>
<p>
You requested the following Path: <b><%=request.RequestURL%></b>
</p>