ServiceStack:服务目录中的静态文件?

我正在将我的独立本土Web服务器转换为使用ServiceStack来提供所有页面和资源。

我从这个问题看出来

使用servicestack提供静态文件

使用Service Stack很容易提供单个静态文件。

在我的本土实现中,在检查URL是否匹配任何特定处理程序(相当于ServiceStack路由)之后,默认处理程序然后在其HttpData目录中检查静态文件以匹配URL。

如果该文件不存在,则会生成404错误。

如果没有其他服务匹配,ServiceStack用于从文件系统提供文件的最佳模式是什么? 请注意,我在没有IIS的独立模式下使用它。

这些文件可以是HTML,PNG,JS和少数其他内容类型。

注意:我看到ServiceStack.Razor包可能有助于我的要求,但我找不到它的文档。 我将就此提出一个单独的问题。

编辑 :我在这个问题中找到了一个参考

使用ServiceStack为根路径’/’创建路由

说明

注册IAppHost.CatchAllHandlers – 调用未匹配的请求。

到目前为止,我还没有找到任何关于如何注册的文档或示例。 注意:我是独立运行的,因此需要在C#中完成,而不是使用XML。

经过大量研究,我发现以下看似有效。

组态

AppHost构造函数中:

  CatchAllHandlers.Add( (httpMethod, pathInfo, filePath) => Tims.Support.StaticFileHandler.Factory( Params.Instance.HttpDataDir, "/", pathInfo ) ); 

工厂

检查文件是否存在,并返回相应的处理程序,如果不处理文件则返回null(因为它不存在)。 这很重要,以便其他url(例如/metadata继续有效)。

处理器

实际处理程序的核心方法非常简单。 通过重写ProcessRequest并使用适当的资源类型返回文件的字节,作业完成。 为简单起见,此版本不包括用于缓存目的的任何日期处理。

示例代码

 public class StaticFileHandler : EndpointHandlerBase { protected static readonly Dictionary ExtensionContentType; protected FileInfo fi; static StaticFileHandler() { ExtensionContentType = new Dictionary (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); } // timeStamp = fi.LastWriteTime; httpRes.AddHeader("Date", DateTime.Now.ToString("R")); httpRes.AddHeader("Content-Type", ExtensionContentType.Safeget(fi.Extension) ?? "text/plain"); } public override object CreateRequest(IHttpRequest request, string operationName) { return null; } public override object GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, object request) { return null; } }