master
Harald Wolff 2019-02-14 16:44:11 +01:00
parent 85caed9f34
commit 1b96e6b95b
4 changed files with 233 additions and 12 deletions

View File

@ -1,35 +1,165 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ln.templates;
namespace ln.http.resources
{
public delegate Resource ResourceTypeHook(DirectoryResource directoryResource, FileInfo fileInfo);
public delegate Resource ResourceTypeHookDelegate(DirectoryResource directoryResource, FileInfo fileInfo);
public class DirectoryResource : Resource
public class DirectoryResource : Resource, TemplateProvider
{
public ResourceTypeHook ResourceTypeHook { get; set; }
public ResourceTypeHookDelegate ResourceTypeHook { get; set; }
DirectoryInfo DirectoryInfo { get; }
Dictionary<string, DirectoryResource> cache = new Dictionary<string, DirectoryResource>();
public virtual DirectoryInfo DirectoryInfo { get; }
protected Dictionary<string, Resource> cache = new Dictionary<string, Resource>();
public DirectoryResource(String path)
:base(System.IO.Path.GetFileName(path))
: base(System.IO.Path.GetFileName(path))
{
DirectoryInfo = new DirectoryInfo(path);
}
public DirectoryResource(Resource container,String path)
:base(container, System.IO.Path.GetFileName(path))
public DirectoryResource(Resource container, String path)
: base(container, System.IO.Path.GetFileName(path))
{
DirectoryInfo = new DirectoryInfo(path);
if (container is DirectoryResource)
{
DirectoryResource parent = container as DirectoryResource;
ResourceTypeHook = parent.ResourceTypeHook;
}
}
protected String GetCombinedPath(string rel)
{
return System.IO.Path.Combine(DirectoryInfo.FullName, rel);
}
public override bool Contains(string name)
{
String cPath = GetCombinedPath(name);
bool exists = File.Exists(cPath) || Directory.Exists(cPath);
if (!exists && cache.ContainsKey(name))
cache.Remove(name);
return exists;
}
public override void AddResource(Resource resource)
{
cache.Add(resource.Name,resource);
}
public override void RemoveResource(Resource resource)
{
if (cache.ContainsValue(resource))
cache.Remove(resource.Name);
}
public override Resource GetResource(string name)
{
if (!Contains(name))
return null;
if (cache.ContainsKey(name))
return cache[name];
String cPath = GetCombinedPath(name);
if (Directory.Exists(cPath))
{
return new DirectoryResource(this, cPath);
}
else if (File.Exists(cPath))
{
FileInfo fileInfo = new FileInfo(cPath);
Resource resource = null;
if (ResourceTypeHook != null)
{
resource = ResourceTypeHook(this, fileInfo);
}
if (resource == null)
{
resource = new FileResource(this, fileInfo);
}
return resource;
}
throw new KeyNotFoundException();
}
public override IEnumerable<Resource> GetResources()
{
return DirectoryInfo.EnumerateFileSystemInfos().Select((x) => GetResource(x.Name));
}
public override HttpResponse GetResponse(HttpRequest httpRequest)
{
if (DefaultResource != null)
return httpRequest.Redirect(String.Join("/", DefaultResource.Path));
throw new NotImplementedException();
}
public Template FindTemplate(string templatePath)
{
if ((templatePath[0] == '/') && (Container is DirectoryResource))
{
return RootDirectoryResource.FindTemplate(templatePath);
}
Resource current = this;
Queue<String> path = new Queue<string>(templatePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries));
while (path.Count > 0)
{
current = current.GetResource(path.Dequeue());
}
if (current is TemplateResource)
{
return (current as TemplateResource).Template;
}
return null;
}
public DirectoryResource RootDirectoryResource
{
get
{
if (Container is DirectoryResource)
{
DirectoryResource parent = Container as DirectoryResource;
return parent.RootDirectoryResource;
}
return this;
}
}
}
public class FileResource : DirectoryResource
{
DirectoryResource DirectoryResource { get; }
public override DirectoryInfo DirectoryInfo => DirectoryResource.DirectoryInfo;
public FileInfo FileInfo { get; }
public FileResource(DirectoryResource directoryResource,FileInfo fileInfo)
:base(directoryResource,fileInfo.Name)
{
DirectoryResource = directoryResource;
FileInfo = fileInfo;
}
public override bool Contains(string name)
{
return false;
}
public override void AddResource(Resource resource)
{
throw new NotImplementedException();
@ -42,15 +172,36 @@ namespace ln.http.resources
public override IEnumerable<Resource> GetResources()
{
throw new NotImplementedException();
return new Resource[0];
}
public override HttpResponse GetResponse(HttpRequest httpRequest)
{
if (DefaultResource != null)
return httpRequest.Redirect(String.Join("/", DefaultResource.Path));
if (!httpRequest.Method.Equals("GET"))
throw new NotImplementedException(String.Format("Method {0} is not supported by this resource", httpRequest.Method));
HttpResponse response = new HttpResponse(httpRequest, FileInfo.OpenRead());
throw new NotImplementedException();
response.SetHeader("content-type", GuessContentType());
return response;
}
public string GuessContentType()
{
String ext = FileInfo.Extension;
switch (ext)
{
case ".html":
return "text/html";
case ".txt":
return "text/plain";
default:
return "application/octet-stream";
}
}
}
}

View File

@ -101,5 +101,15 @@ namespace ln.http.resources
return ResourcePathList.Select((x) => x.Name).ToArray();
}
}
public Resource Root
{
get
{
if (Container != null)
return Container.Root;
return this;
}
}
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using ln.http.resources;
using ln.http;
using ln.templates;
namespace ln.http.resources
{
public class TemplateResource : Resource
{
public Template Template { get; }
public TemplateResource(Resource container,string filename)
:base(container,System.IO.Path.GetFileName(filename))
{
Template = new Template(filename, (container as TemplateProvider));
}
public override IEnumerable<Resource> GetResources()
{
return new Resource[0];
}
public override bool Contains(string name)
{
return false;
}
public override void AddResource(Resource resource)
{
throw new NotImplementedException();
}
public override void RemoveResource(Resource resource)
{
throw new NotImplementedException();
}
public override HttpResponse GetResponse(HttpRequest httpRequest)
{
HttpResponse httpResponse = new HttpResponse(httpRequest);
Template.Context context = new Template.Context(Template);
context.ExpressionContext.AddMappedValue("__root__", Root);
context.ExpressionContext.AddMappedValue("request", httpRequest);
context.ExpressionContext.AddMappedValue("response", httpResponse);
httpResponse.ContentWriter.Write(Template.Generate(context));
return httpResponse;
}
}
}

View File

@ -38,12 +38,17 @@
<Compile Include="Resource.cs" />
<Compile Include="DirectoryResource.cs" />
<Compile Include="BaseResource.cs" />
<Compile Include="TemplateResource.cs" />
</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>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>