Question

The code below is an initial pass at a ServiceStack plugin to support the angularjs configuration $locationProvider.html5Mode(true); when servicestack is self-hosted (as requested here: Routing path with ServiceStack and Serving default index.html page when using Angular HTML5mode and Servicestack on the backend). I think I've got a good general solution, with one last question (other than switching this to a Feature naming convention in line with other plugins).

How can I generically handle any supported default document type in my ProcessRequest? Right now the function assumes markdown. I'm hoping there is a more elegant solution than a switch statement off the file extension. Ideally I'd like to call something that would continue to work as more default document types are supported over time.

// This code does not yet work, and omits required methods for the sake of brevity.
// I'll update with a link to the final plugin, once I get it working.

Public Class Html5ModeHandler : IPlugin
{
    private String pathInfo = String.Empty;

    public void Register(IAppHost appHost)
    {
        appHost.CatchAllHandlers.Add((string method, string pathInfo, string filepath) =>
                                        Factory(method, pathInfo, filepath));
    }

    private Html5ModeHandler(string pathInfo)
    {
        this.pathInfo = pathInfo;
    }

    Public Html5ModeHandler Factory(method, pathInfo, filepath)
    {
        String root = String.Empty;

        // loop through catchallhandlers
        if (EndpointHost.CatchAllHandlers != null)
        {
            foreach (var httpHandlerResolver in EndpointHost.CatchAllHandlers)
            {
                if (httpHandlerResolver == this.Factory) continue; // avoid infinite loop

                var httpHandler = httpHandlerResolver(httpMethod, pathInfo, filePath);
                if (httpHandler != null)
                    // only handle request if no other handler is available
                    return null;
            }
        }

        if (!(GetHandlerForPathInfo(method,pathInfo, pathInfo,filepath) is NotFoundHttpHandler) )
        {
            // GetHandlerForPathInfo replicates most of the logic from 
            // ServiceStackHttpHandlerFactory.GetHandler and ServiceStackHttpHandlerFactory.GetHandlerForPathInfo
            // Bail if it returns something other than a NotFoundHttpHandler

            return null;
        }

        foreach (var defaultDoc in EndpointHost.Config.DefaultDocuments)
        {
            var defaultFileName = Path.Combine(Directory.GetCurrentDirectory(), defaultDoc);
            if (!File.Exists(defaultFileName)) continue;
            root = root ? root : (String)defaultDoc; // keep the first default document found.
        }

        // support HTML5Mode for Single Page App - override NotFoundHttpHandler with default document
        return new Html5ModeHandler("/" + root);
    }

    public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
    {
        // TODO: Generalize to handle any DefaultDocument type 
        MarkdownHandler handler = new MarkdownHandler(this.pathInfo);
        handler.ProcessRequest(httpReq, httpRes, operationName);
    }
}
Was it helpful?

Solution

I've confirmed to my own satisfaction that there's no simple solution. My ProcessRequest method currently looks like this.

   public override void ProcessRequest(
             IHttpRequest httpReq, IHttpResponse httpRes, string operationName)
    {

        if ( FileFormat == DefaultFileFormat.Markdown ) 
        {
            ProcessMarkdownPage(httpReq, httpRes, operationName);
            return;
        }   

        if ( FileFormat == DefaultFileFormat.Razor ) 
        {
            ProcessRazorPage(httpReq, httpRes, operationName);
            return;
        }

        fi.Refresh();
        if (fi.Exists)
        {
            ProcessStaticPage(httpReq, httpRes, operationName);
            return;
        }

        ProcessServerError(httpReq, httpRes, operationName);

    }   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top