Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serving static content via Web API

I'm currently using WebAPI running on OWIN/Katana (on a Windows Azure worker role instance). The client (homepage build with HTML, CSS & Javascript) interacts with the WebAPI via the REST interface.

Static/client related files like the HTML, CSS, Javascript, Images, ... will be saved on Windows Azure Blob Storage.

I now want to serve this static content via WebAPI/OWIN.

First solution was loading the file from blob storage and map a route to a controller which return the blob content of this file as HttpResponse (see here)

This works fine for just one file, but my index.html includes other CSS and Javascript files. So the browser starts looking @ http://[OWIN-Web-Server-URL]/anotherJSfile.js and of course finds nothing because there is no route defined for this. I can't/don't want to define a route for every single file, because the client should get the files from the Blob Storage without any detours over the Web Server (1-2 index/start file would be acceptable, but everything else should be served via blob storage).

Second attempt was to use some external library which provides a "static content"- functionality, but they all didn't work and are in alpha state (see here or here).

Third and not quite acceptable solution would be to redirect from http://[OWIN-Web-Server-URL]/ to the index.html file on the blob storage. This way it might work, but URL would always be something like https://xxx.blob.core.windows.net/jsscripts/index.html, which is not preferable, because if the blob storage name (xxx) would change, every link to the site would also break.

My question is:

Is there currently any solution for serving static files via Web API/OWIN? Or is there any solution in the upcoming Web API 2 release?

like image 995
Robar Avatar asked Sep 18 '13 10:09

Robar


1 Answers

Solution, that works for me:

According to my first solution I serve an index.html and a bootstrapper.js file via a Web API controller.

The index.html file will be loaded from blob storage, formatted on server (gets the storage account endpoint url: https://xxx.blob.core.windows.net/) and returned via HttpResponse (mediatype: text/html). The bootstrapper.js will just be loaded and returned via HttpResponse (mediatype: application/javascript).

The index.html file now calls the bootstrapper.js file with the correct source URL for the remaining static content. The remaining content will be loaded relatively from the given source URL.

In our production system the source URL points to the blob storage, in development enviroment the URL points to a local web server. This is needed, because a HTML file served by a web server can't access files on the filesystem. Therefore a web server (we use the built in webserver in WebStorm) is needed, which provide those files.

index.html file:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>Main Page</title>
    <script type="text/javascript" src="bootstrap-app.js"></script>
    <script type="text/javascript">bootstrapApp('{0}');</script>
</head>
<body></body>
</html>

bootstrapper.js file:

/**
 * Loads all needed files asynchronously into the html file
 */
window.bootstrapApp = function(baseUrl) {
    "use strict";
    var i, assetUrls;

    window.baseUrl = baseUrl;

    assetUrls = [   'https://cdnjs.cloudflare.com/ajax/libs/codemirror/2.36.0/codemirror.min.css',
        'https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/codemirror/2.36.0/codemirror.min.js',
        baseUrl + '../lib/xxx.js',
        baseUrl + '../lib/xxx/xxx.js',
        baseUrl + 'resources/xxx.css',
        baseUrl + 'xxx.js'
    ];

    function endsWidth(string, suffix) {
        return (string.indexOf(suffix, string.length - suffix.length) !== -1);
    }

    // Load all assets from the previously defined array asynchronously in the order they are given in the array
    for (i = 0; i < assetUrls.length; i++) {
        // Load css or js asset
        if (endsWidth(assetUrls[i], 'css')) {
            document.write('<link rel="stylesheet" type="text/css" href="' + assetUrls[i] + '" />');
        } else if (endsWidth(assetUrls[i], 'js')) {
            document.write('<script type="text/javascript" src="' + assetUrls[i] + '"></script>');
        }
    }
};
like image 58
Robar Avatar answered Oct 27 '22 01:10

Robar