3

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

我从这个问题中看到

使用 servicestack 提供静态文件

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

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

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

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

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

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

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

使用 ServiceStack 为根路径“/”创建路由

表示

注册一个IAppHost.CatchAllHandlers- 这被称为不匹配的请求。

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

4

1 回答 1

8

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

配置

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<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);
        }

        // 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;
    }
}
于 2013-04-02T01:11:17.317 回答