UNPKG

tent-discover

Version:

Performes the Tent discovery dance

104 lines (85 loc) 2.59 kB
var request = require('hyperdirect').request var concat = require('concat-stream') var urlMod = require('url') module.exports = function(url, callback) { var req = request(url, { method: 'HEAD' }) req.on('error', function (err) { return callback(err) }) req.on('response', function (res) { var linkHeader = res.headers.link if(!linkHeader) return searchHTML(url, callback) linkHeader = linkHeader.split(',') //split, if there are multiple urls var metaURLs = [] linkHeader.forEach(function(link) { if(link.match(/https:\/\/tent.io\/rels\/meta-post/i)) { //tent link? var metaURL = link.match(/<([^>]*)>/) //get metaURL if(metaURL) { metaURL = processURL(metaURL[1], url) metaURLs.push(metaURL) } } }) if(metaURLs.length === 0) searchHTML(url, callback) //no links in header else getMeta(metaURLs, callback) }) } function searchHTML(url, callback) { var req = request(url, { method: 'GET' }) req.on('error', callback) req.pipe(concat(function(err, data) { if(err) return callback(err) var metaURLs = [] var linkTag = /<link href="([^"]+)" rel="https:\/\/tent\.io\/rels\/meta-post"/g var metaURL while(metaURL = linkTag.exec(data)) { metaURL = processURL(metaURL[1], url) metaURLs.push(metaURL) } if(metaURLs.length > 0) getMeta(metaURLs, callback) else callback(new Error('No meta post found (1)')) })) } function processURL(metaURL, url) { metaURL = urlMod.parse(metaURL) //console.log('HOST' + metaURL.host + 'YO' + typeof metaURL.host +'YO' +url) if(metaURL.host === null) { //relative url? var parsedURL = urlMod.parse(url) //merge metaURL and parsedURL var newObj = {} for (var attrname in parsedURL) { newObj[attrname] = parsedURL[attrname] } for (var attrname in metaURL) { if(metaURL[attrname] !== null) newObj[attrname] = metaURL[attrname] } metaURL = newObj } metaURL = urlMod.format(metaURL) return metaURL } function getMeta(metaURLs, callback) { var i = 0 var tryURL = function() { if(!metaURLs[i]) return callback(new Error('No meta post found (2)')) var req = request(metaURLs[i], { method: 'GET' }) req.on('error', callback) var response req.on('response', function(res) { response = res }) req.pipe(concat(function(err, data) { if(err) return callback(new Error(metaURLs[i] + err)) try { data = JSON.parse(data) } catch(e) { i++ return tryURL() } if(response.statusCode < 200 || response.statusCode >= 300) { i++ return tryURL() } callback(null, data, response) })) } tryURL() }