123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- var debug = require('debug')('ylt:cdnDetector');
- var Q = require('q');
- var url = require('url');
- var dns = require('dns');
- var cdnDetector = require('cdn-detector');
- // This module checks my multiple ways if a request was served by a CDN
- var CDNDetector = function() {
- function detectCDN(entry) {
- var urlObject = url.parse(entry.url);
- debug('Start checking CDN for %s, host is %s', entry.url, urlObject.host);
- // 1st, the fastest check: the domain is directly recognized as a CDN
- return checkDomainDirectly(entry)
- .fail(function() {
- // 2nd, check the response headers
- return checkHeaders(entry)
- .fail(function() {
- // 3rd, check the Name Servers
- return checkNameServers(entry)
- .fail(function(entry) {
- // None of the above worked, we didn't find any trace of a CDN
- return entry;
- });
- })
- });
- }
- return {
- detectCDN: detectCDN
- };
- // Compares the URL's domain to a list of know CDN, just in case
- function checkDomainDirectly(entry) {
- var deferred = Q.defer();
- var result = checkHostname(url.parse(entry.url).host);
- if (result === null) {
- deferred.reject(entry);
- } else {
- entry.weightCheck.cdn = result;
- deferred.resolve(entry);
- }
-
- return deferred.promise;
- }
- // Compares a list of HTTP response headers to a matching list
- // For example, if there is an X-Akamai-Request-Id header, we know it is Akamai
- function checkHeaders(entry) {
- var deferred = Q.defer();
- var result = cdnDetector.detectFromHeaders(entry.weightCheck.headers);
- debug('Headers of %s were compared to the list. Result: %s', entry.url, JSON.stringify(result));
- if (result === null) {
- deferred.reject(entry);
- } else {
- entry.weightCheck.cdn = result.cdn;
- deferred.resolve(entry);
- }
-
- return deferred.promise;
- }
- function checkNameServers(entry) {
- var deferred = Q.defer();
- var hostname = url.parse(entry.url).host;
- // Send a request to get the Name Servers list
- // https://nodejs.org/api/dns.html#dns_dns_resolvens_hostname_callback
- dns.resolveNs(hostname, function(error, nameServers) {
- if (error) {
- debug(error);
- debug('Could not find Name Servers for %s', hostname);
- deferred.reject(entry);
- } else {
- debug('Name Servers for %s are ["%s"]', hostname, nameServers.join('", "'));
- var cdn = nameServers.map(checkHostname).find(function(entry) {
- return entry !== null;
- });
- if (cdn) {
- entry.weightCheck.cdn = cdn;
- deferred.resolve(entry);
- } else {
- deferred.reject(entry);
- }
- }
- });
- return deferred.promise;
- }
- // Compares the hostname to a matching list of hostnames
- function checkHostname(hostname) {
- var result = cdnDetector.detectFromHostname(hostname);
- debug('Hostname %s was compared to the list. Result: %s', hostname, JSON.stringify(result));
- return result ? result.cdn : null;
- }
- // Find an IP address with a DNS lookup
- function getIP(hostname) {
- var deferred = Q.defer();
- // https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback
- dns.lookup(hostname, {family: 4}, function(error, address) {
- if (error) {
- debug('Could not find IP address for %s', hostname);
- } else {
- debug('The IP address for %s is %s', hostname, address);
- }
- deferred.resolve(error ? null : address);
- });
- return deferred.promise;
- }
- // Compares the IP address agains a list of IP ranges
- function checkIPAddress(address) {
- var deferred = Q.defer();
- var result = cdnDetector.detectFromHeaders(headers);
- debug('Headers were compared to the list. Result: %s', JSON.stringify(result));
- if (result === null) {
- deferred.reject();
- } else {
- deferred.resolve(result.cdn);
- }
- return deferred.promise;
- }
- function saveCDN(cdnName) {
- }
- };
- module.exports = new CDNDetector();
|