lib/resolvers/http.js

lib/ AssetGraph.js errors.js index.js query.js
assets/ Asset.js Atom.js CacheManifest.js CoffeeScript.js Css.js Flash.js Gif.js Htc.js Html.js I18n.js Ico.js Image.js JavaScript.js Jpeg.js Json.js KnockoutJsTemplate.js Less.js Png.js Rss.js StaticUrlMap.js Stylus.js Text.js Xml.js index.js
relations/ CacheManifestEntry.js CssAlphaImageLoader.js CssBehavior.js CssFontFaceSrc.js CssImage.js CssImport.js CssUrlTokenRelation.js HtmlAlternateLink.js HtmlAnchor.js HtmlAppleTouchStartupImage.js HtmlApplet.js HtmlAudio.js HtmlCacheManifest.js HtmlConditionalComment.js HtmlDataBindAttribute.js HtmlEdgeSideInclude.js HtmlEmbed.js HtmlFrame.js HtmlIFrame.js HtmlIFrameSrcDoc.js HtmlImage.js HtmlInlineScriptTemplate.js HtmlKnockoutContainerless.js HtmlObject.js HtmlRelation.js HtmlRequireJsMain.js HtmlScript.js HtmlShortcutIcon.js HtmlStyle.js HtmlStyleAttribute.js HtmlVideo.js HtmlVideoPoster.js JavaScriptAmdDefine.js JavaScriptAmdRequire.js JavaScriptCommonJsRequire.js JavaScriptExtJsRequire.js JavaScriptGetStaticUrl.js JavaScriptGetText.js JavaScriptInclude.js JavaScriptShimRequire.js JavaScriptTrHtml.js Relation.js StaticUrlMapEntry.js index.js
resolvers/ data.js extJs4Dir.js file.js fixedDirectory.js http.js index.js javascript.js
transforms/ addCacheManifest.js bundleRelations.js bundleRequireJs.js compileCoffeeScriptToJavaScript.js compileLessToCss.js compileStylusToCss.js compressJavaScript.js convertCssImportsToHtmlStyles.js convertHtmlStylesToInlineCssImports.js convertStylesheetsToInlineStyles.js drawGraph.js executeJavaScriptInOrder.js externalizeRelations.js flattenStaticIncludes.js inlineCssImagesWithLegacyFallback.js inlineRelations.js loadAssets.js mergeIdenticalAssets.js minifyAssets.js moveAssets.js moveAssetsInOrder.js populate.js prettyPrintAssets.js pullGlobalsIntoVariables.js registerRequireJsConfig.js removeAssets.js removeRelations.js setAssetContentType.js setAssetEncoding.js setAssetExtension.js setHtmlImageDimensions.js startOverIfAssetSourceFilesChange.js writeAssetsToDisc.js writeAssetsToStdout.js writeStatsToStderr.js
util/ deepCopy.js extendWithGettersAndSetters.js fsTools.js getImageInfoFromBuffers.js memoizeAsyncAccessor.js uniqueId.js urlTools.js
var request = require('request'),
    _ = require('underscore'),
    passError = require('passerror'),
    httpErrors = require('httperrors');

require('bufferjs');

module.exports = function () {
    return function http(assetConfig, fromUrl, cb) {
        var url = assetConfig.url;
        assetConfig.rawSrcProxy = function (cb) {
            var matchUrl = url.match(/^([^#]*)((?:#.*)?)$/),
                urlWithoutFragmentIdentifier = matchUrl[1],
                fragmentIdentifier = matchUrl[2],
                requestOptions = http.requestOptions || {},
                numRetries = requestOptions.numRetries || 0;

            (function doRequest() {
                // Hack: Allows you to control the request options by setting the 'requestOptions' of the returned function to
                // an object.
                var req = request(_.defaults({
                    uri: urlWithoutFragmentIdentifier,
                    onResponse: true
                }, requestOptions), function (err, response) {
                    if (err) {
                        if (typeof numRetries === 'number' && numRetries > 0) {
                            numRetries -= 1;
                            return doRequest();
                        } else {
                            return cb(err);
                        }
                    }
                    if (response.statusCode >= 400) {
                        return cb(new (httpErrors[response.statusCode] || httpErrors.BadGateway)({
                            message: 'Got ' + response.statusCode + ' error retrieving ' + urlWithoutFragmentIdentifier,
                            url: urlWithoutFragmentIdentifier
                        }));
                    }
                    var metadata = {
                            url: req.uri.href + fragmentIdentifier // Might be different from the originally requested url if redirects were followed
                        },
                        buffers = [],
                        contentType = response.headers['content-type'];
                    if (contentType) {
                        var matchContentType = contentType.match(/^\s*([\w\-\+\.]+\/[\w\-\+\.]+)(?:\s|;|$)/i);
                        if (matchContentType) {
                            metadata.contentType = matchContentType[1].toLowerCase();
                            var matchCharset = contentType.match(/;\s*charset\s*=\s*(['"]|)\s*([\w\-]+)\s*\1(?:\s|;|$)/i);
                            if (matchCharset) {
                                metadata.encoding = matchCharset[2].toLowerCase();
                            }
                        } else {
                            console.warn("resolvers.http: Couldn't parse Content-Type " + response.headers['content-type'] + " while fetching " + url);
                        }
                    }
                    if ('etag' in response.headers) {
                        metadata.etag = response.headers.etag;
                    }
                    if ('cache-control' in response.headers) {
                        metadata.cacheControl = response.headers['cache-control'];
                    }
                    ['date', 'last-modified'].forEach(function (headerName) {
                        if (headerName in response.headers) {
                            metadata[headerName.replace(/-([a-z])/, function ($0, ch) {
                                return ch.toUpperCase();
                            })] = new Date(response.headers[headerName]);
                        }
                    });
                    response.on('data', function (buffer) {
                        buffers.push(buffer);
                    }).on('end', function () {
                        cb(null, Buffer.concat(buffers), metadata);
                    }).on('error', cb);
                });
            }());
        };
        assetConfig.isResolved = true;
        process.nextTick(function () {
            cb(null, assetConfig);
        });
    };
};