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

时间:2013-04-01 13:08:55

标签: c# servicestack

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

我从这个问题看出来

Serving a static file with servicestack

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

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

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

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

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

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

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

Create route for root path, '/', with ServiceStack

指示

  

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

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

1 个答案:

答案 0 :(得分:8)

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

配置

AppHost构造函数中:

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

工厂

检查文件是否存在,并返回相应的处理程序,如果不处理文件则返回null(因为它不存在)。这很重要,以便其他网址(例如/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;
    }
}