Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Simple HTTP Status Interface #935

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added 3rdparty/MiniHttpd/MiniHttpd.dll
Binary file not shown.
1,503 changes: 1,503 additions & 0 deletions 3rdparty/MiniHttpd/MiniHttpd.xml

Large diffs are not rendered by default.

240 changes: 240 additions & 0 deletions 3rdparty/MiniHttpd_src/Aspx/AspxAppDirectory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
using System;
using System.Collections;
using System.Xml;
using System.Web;
using System.Web.Hosting;
using System.Reflection;
using System.IO;
using MiniHttpd;

namespace MiniHttpd.Aspx
{
/// <summary>
/// Represents a directory containing an ASPX web application.
/// </summary>
[Serializable]
public class AspxAppDirectory : DriveDirectory
{
/// <summary>
/// Creates a new <see cref="AspxAppDirectory"/> with the specified path and parent.
/// </summary>
/// <param name="path">The full path of the web application root.</param>
/// <param name="parent">The parent directory to which this directory will belong.</param>
public AspxAppDirectory(string path, IDirectory parent) : base(path, parent)
{
virtPath = HttpWebServer.GetDirectoryPath(this);

CreateAssemblyInBin(path);

CreateAppHost();

configFileWatcher.Path = path;
configFileWatcher.Filter = "Web.config";
configFileWatcher.Created += new FileSystemEventHandler(configFileWatcher_Changed);
configFileWatcher.Changed += new FileSystemEventHandler(configFileWatcher_Changed);
configFileWatcher.Deleted += new FileSystemEventHandler(configFileWatcher_Changed);
configFileWatcher.Renamed += new RenamedEventHandler(configFileWatcher_Renamed);

configFileWatcher.EnableRaisingEvents = true;

LoadWebConfig(System.IO.Path.Combine(path, "Web.config"));
}

/// <summary>
/// Creates a root <see cref="AspxAppDirectory"/> with the specified path.
/// </summary>
/// <param name="path">The full path of the directory on disk.</param>
public AspxAppDirectory(string path) : this (path, null)
{
}

/// <summary>
/// Shut down app domain and delete bin/minihttpd.dll.
/// </summary>
public override void Dispose()
{
appHost.Unload();
if(binFolder != null)
{
if(Directory.Exists(binFolder))
{
string assemblyPath = System.IO.Path.Combine(
binFolder,
System.IO.Path.GetFileName(
new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath));
if(File.Exists(assemblyPath))
File.Delete(assemblyPath);

if(Directory.GetFileSystemEntries(binFolder).Length == 0)
Directory.Delete(binFolder);
}
}
base.Dispose ();
}

string virtPath;
AspxAppHost appHost;
[NonSerialized] XmlDocument configFile;
ArrayList httpHandlers = new ArrayList();

string binFolder;

FileSystemWatcher configFileWatcher = new FileSystemWatcher();

internal string VirtualPath
{
get
{
return virtPath;
}
}

void CreateAppHost()
{
appHost = ApplicationHost.CreateApplicationHost(typeof(AspxAppHost), virtPath, Path) as AspxAppHost;
}

internal void ProcessRequest(HttpRequest request, IFile file)
{
if(!(file is DriveFile))
throw new ArgumentException("File must be available on disk.");
try
{
appHost.ProcessRequest(request, file as DriveFile, virtPath, Path);
}
catch(AppDomainUnloadedException)
{
CreateAppHost();
ProcessRequest(request, file);
}
}

/// <summary>
/// Copies the host assembly to the <c>bin</c> folder of the web application if it doesn't exist in the GAC.
/// The assembly is needed by ASP.NET to access from the web app's domain.
/// </summary>
/// <param name="appPath">The full path of the web application directory.</param>
void CreateAssemblyInBin(string appPath)
{
Assembly thisAssembly = Assembly.GetExecutingAssembly();

if(!thisAssembly.GlobalAssemblyCache)
{
string copiedAssemblyPath = null;
try
{

// Create the folder if it doesn't exist, flag it as hidden
binFolder = System.IO.Path.Combine(appPath, "bin");
if(!Directory.Exists(binFolder))
{
Directory.CreateDirectory(binFolder);
File.SetAttributes(binFolder, FileAttributes.Hidden);
}

//TODO: implement httphandlers, lock httpHandlers

// Delete the file if it exists, copy to bin
string assemblyPath = new Uri(thisAssembly.CodeBase).LocalPath;
copiedAssemblyPath = System.IO.Path.Combine(binFolder, System.IO.Path.GetFileName(assemblyPath));
if(File.Exists(copiedAssemblyPath))
File.Delete(copiedAssemblyPath);
File.Copy(assemblyPath, copiedAssemblyPath);

}
catch(IOException)
{
if(!File.Exists(copiedAssemblyPath))
throw;

if(thisAssembly.FullName != AssemblyName.GetAssemblyName(copiedAssemblyPath).FullName)
throw;
}
}
}

void LoadWebConfig(string path)
{
try
{
httpHandlers.Clear();
configFile = new XmlDocument();
configFile.Load(path);

XmlNode handlersNode = configFile.DocumentElement.SelectSingleNode("/configuration/system.web/httpHandlers");
if(handlersNode == null)
return;

lock(httpHandlers)
{
foreach(XmlNode node in handlersNode)
{
switch(node.Name)
{
case "add":
{
if(node.Attributes["verb"] == null)
break;
if(node.Attributes["path"] == null)
break;
if(node.Attributes["type"] == null)
break;

bool validate = false;

try
{
if(node.Attributes["validate"] != null)
validate = bool.Parse(node.Attributes["validate"].Value);
}
catch(FormatException)
{
validate = false;
}

HttpHandler handler = new HttpHandler(node.Attributes["verb"].Value, node.Attributes["path"].Value, node.Attributes["type"].Value, validate);
httpHandlers.Remove(handler);
httpHandlers.Add(handler);

break;
}
case "remove":
{
if(node.Attributes["verb"] == null)
break;
if(node.Attributes["path"] == null)
break;

HttpHandler handler = new HttpHandler(node.Attributes["verb"].Value, node.Attributes["path"].Value, null, false);
httpHandlers.Remove(handler);

break;
}
case "clear":
{
httpHandlers.Clear();

break;
}
}
}
}
}
catch(Exception)
{
httpHandlers.Clear();
configFile = null;
}
}

private void configFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
LoadWebConfig(e.FullPath);
}

private void configFileWatcher_Renamed(object sender, RenamedEventArgs e)
{
LoadWebConfig(e.FullPath);
}
}
}
29 changes: 29 additions & 0 deletions 3rdparty/MiniHttpd_src/Aspx/AspxAppHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.IO;
using System.Web;
using System.Web.Hosting;

namespace MiniHttpd.Aspx
{
/// <summary>
/// Summary description for AspxAppHost.
/// </summary>
internal class AspxAppHost : MarshalByRefObject
{
public void ProcessRequest(HttpRequest request, DriveFile file, string virtualPath, string physicalDir)
{
HttpRuntime.ProcessRequest(new WorkerRequest(request, file, virtualPath, physicalDir));
}

public override object InitializeLifetimeService()
{
return null;
}

public void Unload()
{
HttpRuntime.UnloadAppDomain();
}

}
}
Loading