-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
64 lines (51 loc) · 2 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
const debug = require('debug')('resolveEndpoint')
const fetch = require('node-fetch')
const is = require('is_js')
const cheerio = require('cheerio')
const parseHeaders = require('parse-link-header')
const fullUrl = (incomingString, destination) => {
// Full URL
if (is.url(incomingString)) return incomingString
// Relative URL
const destinationUrl = new URL(destination)
let combinedUrl = new URL(incomingString, incomingString.startsWith('/') ? destinationUrl.origin : destinationUrl )
return combinedUrl.href
}
const resolveEndpoint = async (destination, options = {}) => {
try {
if (!destination) throw new Error('Required parameter not supplied: destination')
if (is.not.url(destination)) throw new Error('Parameter must be a URL: destination')
// get back HTML text
// TODO: get back just headers initially, then request body if no endpoints found
let res = await fetch(destination, {
'method' : 'GET'
})
if (!res.ok) throw new Error(`Received a bad destination: ${res.statusCode}`)
// HEADERS
// Check headers for valid links
if (res.headers.has('link')) {
let headers = parseHeaders(res.headers.get('link'))
if (headers.webmention) return fullUrl(headers.webmention.url, destination)
}
// HTML
// Convert received HTML to parsable DOM
let resolvedEndpoint = await res.text()
const root = cheerio.load(resolvedEndpoint)
// Find all rel="webmention" instances
let relWebmentions = root('[rel~="webmention"]')
// Loop over all webmentions, checking for validity.
// The first valid webmention is always the correct one,
// so we can return immediately.
for (const relWebmention of relWebmentions) {
if (is.existy(relWebmention.attribs.href)) {
if (is.empty(relWebmention.attribs.href)) return destination
return fullUrl(relWebmention.attribs.href, destination)
}
}
throw false
} catch (error) {
debug(error)
throw error
}
}
module.exports = resolveEndpoint