Skip to content

Commit

Permalink
build: ensure to resolve HEAD requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Kikobeats committed Jan 26, 2020
1 parent e70f13c commit c7016f0
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 24 deletions.
39 changes: 28 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,37 @@ const createRequest = method => async (url, opts) => {
}
}

const get = createRequest('get')

module.exports = async (url, opts = {}) => {
const wrapRequest = fetch => async (url, opts = {}) => {
const { href: encodedUrl } = new URL(url)
const { isFulfilled, value, error } = await get(encodedUrl, opts)
const { isFulfilled, value, error } = await fetch(encodedUrl, opts)

return isFulfilled
? value
: {
redirectStatusCodes: [],
redirectUrls: [],
statusCode: error.statusCode || 404,
headers: error.headers || {},
statusMessage: error.statusMessage || 'Not Found',
url: error.url || url
}
redirectStatusCodes: [],
redirectUrls: [],
statusCode: error.statusCode || 404,
headers: error.headers || {},
statusMessage: error.statusMessage || 'Not Found',
url: error.url || url
}
}

const fromGET = wrapRequest(createRequest('get'))
const fromHEAD = wrapRequest(createRequest('head'))

const isReachable = ({ statusCode }) => statusCode >= 200 && statusCode < 400

module.exports = async (url, opts = {}) => {
const { href: encodedUrl } = new URL(url)

const get = await fromGET(encodedUrl, opts)
if (isReachable(get)) return get

const head = await fromHEAD(encodedUrl, opts)
if (isReachable(head)) return head

return head.statusCode < get.statusCode ? head : get
}

module.exports.isReachable = isReachable
20 changes: 9 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,14 @@
}
},
"lint-staged": {
"linters": {
"package.json": [
"finepack"
],
"*.js": [
"prettier-standard"
],
"*.md": [
"standard-markdown"
]
}
"package.json": [
"finepack"
],
"*.js": [
"prettier-standard"
],
"*.md": [
"standard-markdown"
]
}
}
29 changes: 27 additions & 2 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,34 @@ const test = require('ava')

const reachableUrl = require('..')

const { isReachable } = reachableUrl

test('resolve GET request', async t => {
const url = 'https://httpbin.org/get'
const res = await reachableUrl(url)
t.deepEqual(res.redirectUrls, [])
t.deepEqual(res.redirectStatusCodes, [])
t.is(res.url, url)
t.is(200, res.statusCode)
t.true(isReachable(res))
})

test('resolve HEAD requests', async t => {
const url =
'https://r3---sn-h5q7kne6.googlevideo.com/videoplayback?expire=1580077455&ei=Lr0tXsbYOYT3xgLT3qyIAQ&ip=88.0.25.71&id=o-ALGvCUB-YHc3EFopGRyEo8yA5CXmWwMA_W7aAlXisgjT&itag=140&source=youtube&requiressl=yes&mm=31%2C26&mn=sn-h5q7kne6%2Csn-aigzrn7d&ms=au%2Conr&mv=m&mvi=2&pl=16&initcwndbps=1136250&vprv=1&mime=audio%2Fmp4&gir=yes&clen=2248120&dur=141.502&lmt=1507952811949144&mt=1580055764&fvip=3&keepalive=yes&fexp=23842630&c=WEB&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHylml4wRAIgW5DeEEU8ubxNJ1uWksvGwsu8NlAImp6iDS2XDIdtKfoCIE354W9zSElzKPRZHWLdRYqTljSXY9E-eGO_lJH4vf2D&sig=ALgxI2wwRQIhAOXja7uKOOyS-vabn08tHzOMJ-bpwl_5L0LP8n-K-GAFAiBwQMN-M8XNwBBWf8X_r7FOQgweolR_R-f73MYaZ6wXdg==&ratebypass=yes'
const res = await reachableUrl(url, { timeout: 5000 })
t.deepEqual(res.redirectUrls, [])
t.deepEqual(res.redirectStatusCodes, [])
t.is(res.url, url)
t.is(200, res.statusCode)
t.true(isReachable(res))
})

test('resolve prerender GET request', async t => {
const url = 'https://www.instagram.com/teslamotors'
const res = await reachableUrl(url)
t.is(200, res.statusCode)
t.true(isReachable(res))
})

test('resolve redirect', async t => {
Expand All @@ -27,6 +42,7 @@ test('resolve redirect', async t => {
t.deepEqual(res.redirectStatusCodes, [301])
t.is('https://github.com/microlinkhq/splashy', res.url)
t.is(200, res.statusCode)
t.true(isReachable(res))
})

test('resolve multiple redirects', async t => {
Expand All @@ -41,12 +57,14 @@ test('resolve multiple redirects', async t => {
t.deepEqual(res.redirectStatusCodes, [302, 302, 302])
t.is('https://httpbin.org/get', res.url)
t.is(200, res.statusCode)
t.true(isReachable(res))
})

test('passing options', async t => {
const url = 'https://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.com%2F'
const res = await reachableUrl(url, { followRedirect: false })
t.is(302, res.statusCode)
t.true(isReachable(res))
})

test('resolve non encoding urls', async t => {
Expand All @@ -59,6 +77,7 @@ test('resolve non encoding urls', async t => {
'https://httpbin.org/anything/pr-experterna:-s-forsoker-ta-kommando-over-%22svenskhet%22-i-valfilm-fZlCYGEtZA'
)
t.is(200, resOne.statusCode)
t.true(isReachable(resOne))

const urlTwo =
'https://httpbin.org/anything/@Acegikmo/the-ever-so-lovely-bézier-curve-eb27514da3bf'
Expand All @@ -69,6 +88,7 @@ test('resolve non encoding urls', async t => {
'https://httpbin.org/anything/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf'
)
t.is(200, resTwo.statusCode)
t.true(isReachable(resTwo))
})

test('resolve already encoded urls', async t => {
Expand All @@ -81,16 +101,17 @@ test('resolve already encoded urls', async t => {
'https://httpbin.org/anything/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf'
)
t.is(200, resThree.statusCode)
t.true(isReachable(resThree))
})

test('keep original query search', async t => {
const url =
'https://www.b92.net/biz/vesti/srbija.php?yyyy=2018&mm=11&dd=05&nav_id=1465369'
const url = 'https://www.b92.net/biz/vesti/srbija.php?yyyy=2018&mm=11&dd=05&nav_id=1465369'
const res = await reachableUrl(url)
t.is(res.url, url)
t.is(200, res.statusCode)
t.is(res.statusMessage, 'OK')
t.true(Object.keys(res.headers).length > 0)
t.true(isReachable(res))
})

test('handle 404 urls', async t => {
Expand All @@ -99,6 +120,7 @@ test('handle 404 urls', async t => {
t.is(res.url, url)
t.is(res.statusCode, 404)
t.is(res.statusMessage, 'Not Found')
t.false(isReachable(res))
})

test('handle 201 urls', async t => {
Expand All @@ -107,6 +129,7 @@ test('handle 201 urls', async t => {
t.is(res.url, url)
t.is(res.statusCode, 201)
t.is(res.statusMessage, 'CREATED')
t.true(isReachable(res))
})

test('handle 500 urls', async t => {
Expand All @@ -115,6 +138,7 @@ test('handle 500 urls', async t => {
t.is(res.url, url)
t.is(res.statusCode, 500)
t.is(res.statusMessage, 'INTERNAL SERVER ERROR')
t.false(isReachable(res))
})

test('handle DNS errors', async t => {
Expand All @@ -125,4 +149,5 @@ test('handle DNS errors', async t => {
t.is(res.statusCode, 404)
t.is(res.statusMessage, 'Not Found')
t.is(Object.keys(res.headers).length, 0)
t.false(isReachable(res))
})

0 comments on commit c7016f0

Please sign in to comment.