After much research, I found the following that seems effective.
Configuration
In the AppHost constructor:
CatchAllHandlers.Add( (httpMethod, pathInfo, filePath) => Tims.Support.StaticFileHandler.Factory( Params.Instance.HttpDataDir, "/", pathInfo ) );
factory
Checks for a file and returns the appropriate handler or returns null if it does not process the file (because it does not exist). This is important, so other URLs (e.g. /metadata continue to work.
Handler
The basic method of the actual handler is very simple. ProcessRequest and returning the bytes of the file with the corresponding resource type, the task is executed. This version for simplicity does not include date processing for caching purposes.
Code example
public class StaticFileHandler : EndpointHandlerBase { protected static readonly Dictionary<string, string> ExtensionContentType; protected FileInfo fi; static StaticFileHandler() { ExtensionContentType = new Dictionary<string, string> (StringComparer.InvariantCultureIgnoreCase) { { ".text", "text/plain" }, { ".js", "text/javascript" }, { ".css", "text/css" }, { ".html", "text/html" }, { ".htm", "text/html" }, { ".png", "image/png" }, { ".ico", "image/x-icon" }, { ".gif", "image/gif" }, { ".bmp", "image/bmp" }, { ".jpg", "image/jpeg" } }; } public string BaseDirectory { protected set; get; } public string Prefix { protected set; get; } public StaticFileHandler(string baseDirectory, string prefix) { BaseDirectory = baseDirectory; Prefix = prefix; } private StaticFileHandler(FileInfo fi) { this.fi = fi; } public static StaticFileHandler Factory(string baseDirectory, string prefix, string pathInfo) { if (!pathInfo.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) { return null; } var fn = baseDirectory + "/" + pathInfo.After(prefix.Length); var fi = new System.IO.FileInfo(fn); if (!fi.Exists) { return null; } return new StaticFileHandler(fi); } public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName) { using (var source = new System.IO.FileStream(fi.FullName, System.IO.FileMode.Open)) { var bytes = source.ReadAllBytes(); httpRes.OutputStream.Write(bytes, 0, bytes.Length); }