2022-01-11 16:51:15 +00:00
|
|
|
import { Eltro as t, assert} from 'eltro'
|
2022-01-21 02:43:48 +00:00
|
|
|
import fs from 'fs/promises'
|
2022-01-11 16:51:15 +00:00
|
|
|
import http from 'http'
|
2022-01-21 02:43:48 +00:00
|
|
|
import Util from '../core/util.mjs'
|
2022-01-11 16:51:15 +00:00
|
|
|
import { request } from '../core/client.mjs'
|
|
|
|
|
2022-01-21 02:43:48 +00:00
|
|
|
const util = new Util(import.meta.url)
|
|
|
|
const testTargetFile = util.getPathFromRoot('./filetest.html')
|
2022-01-11 16:51:15 +00:00
|
|
|
const port = 61412
|
|
|
|
const defaultHandler = function(req, res) {
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end('{"a":1}');
|
|
|
|
}
|
|
|
|
let server = null
|
|
|
|
let prefix = `http://localhost:${port}/`
|
|
|
|
let handler = defaultHandler
|
|
|
|
|
|
|
|
t.before(function(cb) {
|
|
|
|
server = http.createServer(function(req, res) {
|
|
|
|
req.on('error', function(err) {
|
|
|
|
console.log('error', err)
|
|
|
|
})
|
|
|
|
res.on('error', function(err) {
|
|
|
|
console.log('error', err)
|
|
|
|
})
|
|
|
|
handler(req, res)
|
|
|
|
})
|
|
|
|
server.listen(port, cb)
|
|
|
|
})
|
|
|
|
|
2022-01-21 02:43:48 +00:00
|
|
|
t.after(function() {
|
|
|
|
return fs.rm(testTargetFile)
|
|
|
|
.catch(function() { })
|
|
|
|
})
|
|
|
|
|
2022-01-11 16:51:15 +00:00
|
|
|
t.describe('Basics', function() {
|
|
|
|
t.beforeEach(function() {
|
|
|
|
handler = defaultHandler
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should require valid config', async function() {
|
|
|
|
function checkError(err) {
|
|
|
|
assert.match(err.message, /config/i)
|
|
|
|
}
|
|
|
|
|
|
|
|
await assert.isRejected(request(prefix)).then(checkError)
|
|
|
|
await assert.isRejected(request('', prefix)).then(checkError)
|
|
|
|
await assert.isRejected(request([], prefix)).then(checkError)
|
|
|
|
await assert.isRejected(request(123, prefix)).then(checkError)
|
|
|
|
await assert.isRejected(request(0, prefix)).then(checkError)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should fail if url is invalid', async function() {
|
|
|
|
function checkError(err) {
|
|
|
|
assert.match(err.message, /invalid/i)
|
|
|
|
assert.match(err.message, /url/i)
|
|
|
|
}
|
|
|
|
|
|
|
|
await assert.isRejected(request({}, 123)).then(checkError)
|
|
|
|
await assert.isRejected(request({}, [])).then(checkError)
|
|
|
|
await assert.isRejected(request({}, {})).then(checkError)
|
|
|
|
await assert.isRejected(request({}, '')).then(checkError)
|
|
|
|
await assert.isRejected(request({}, 'asdf')).then(checkError)
|
|
|
|
await assert.isRejected(request({}, 'httpppp')).then(checkError)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.describe('Request', function() {
|
|
|
|
t.test('should work normally', async function() {
|
|
|
|
let res = await request({}, prefix)
|
|
|
|
assert.deepEqual(res.body, {a:1})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should follow redirects', async function() {
|
|
|
|
let counter = 0
|
|
|
|
handler = function(req, res) {
|
|
|
|
if (counter < 3) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.setHeader('Location', encodeURI(prefix))
|
|
|
|
res.end();
|
|
|
|
counter++
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.strictEqual(req.url, '/')
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end('{"a":1}');
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let res = await request({}, prefix)
|
|
|
|
assert.deepEqual(res.body, {a:1})
|
|
|
|
assert.strictEqual(counter, 3)
|
|
|
|
})
|
|
|
|
|
2022-01-21 02:43:48 +00:00
|
|
|
t.test('should fail gracefully if HTML is received', async function() {
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end(`<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
</body>
|
|
|
|
</html>`);
|
|
|
|
}
|
|
|
|
let err = await assert.isRejected(request({}, prefix))
|
|
|
|
assert.match(err.message, /html/i)
|
|
|
|
assert.notMatch(err.message, /Unexpected token/i)
|
|
|
|
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end(`<html>
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
</body>
|
|
|
|
</html>`);
|
|
|
|
}
|
|
|
|
err = await assert.isRejected(request({}, prefix))
|
|
|
|
assert.match(err.message, /html/i)
|
|
|
|
assert.notMatch(err.message, /Unexpected token/i)
|
|
|
|
})
|
|
|
|
|
2022-01-11 16:51:15 +00:00
|
|
|
t.test('should fail if infinite redirect', async function() {
|
|
|
|
const assertRelativeLocation = 'some/text/here'
|
|
|
|
const assertLocation = prefix + assertRelativeLocation
|
|
|
|
let counter = 0
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.setHeader('Location', encodeURI(assertLocation))
|
|
|
|
if (counter === 0) {
|
|
|
|
assert.strictEqual(req.url, '/')
|
|
|
|
} else {
|
|
|
|
assert.strictEqual(req.url, '/' + assertRelativeLocation)
|
|
|
|
}
|
|
|
|
res.end();
|
|
|
|
counter++
|
|
|
|
}
|
|
|
|
|
|
|
|
let err = await assert.isRejected(request({}, prefix))
|
|
|
|
assert.strictEqual(counter, 6)
|
|
|
|
assert.match(err.message, /redirect/i)
|
|
|
|
assert.match(err.message, new RegExp(assertRelativeLocation))
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should fail if redirect is missing location', async function() {
|
|
|
|
let counter = 0
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.end();
|
|
|
|
counter++
|
|
|
|
}
|
|
|
|
|
|
|
|
let err = await assert.isRejected(request({}, prefix))
|
|
|
|
assert.strictEqual(counter, 1)
|
|
|
|
assert.match(err.message, /redirect/i)
|
|
|
|
assert.match(err.message, /location/i)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should follow relative redirects', async function() {
|
|
|
|
const assertUrl = 'asdf1234'
|
|
|
|
let counter = 0
|
|
|
|
let url = ''
|
|
|
|
handler = function(req, res) {
|
|
|
|
if (counter < 1) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.setHeader('Location', encodeURI(assertUrl))
|
|
|
|
res.end();
|
|
|
|
counter++
|
|
|
|
return
|
|
|
|
}
|
|
|
|
url = req.url
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end('{"a":1}');
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let res = await request({}, prefix)
|
|
|
|
assert.deepEqual(res.body, {a:1})
|
|
|
|
assert.strictEqual(counter, 1)
|
|
|
|
assert.strictEqual(url, '/' + assertUrl)
|
|
|
|
|
|
|
|
counter = 0
|
|
|
|
res = await request({}, prefix + 'some/url/here')
|
|
|
|
assert.deepEqual(res.body, {a:1})
|
|
|
|
assert.strictEqual(counter, 1)
|
|
|
|
assert.strictEqual(url, '/some/url/' + assertUrl)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.timeout(30).test('should support timeout on invalid url', async function() {
|
|
|
|
// blocked off port, should time out
|
|
|
|
let err = await assert.isRejected(request({ timeout: 15 }, 'http://git.nfp.is:8080'))
|
|
|
|
assert.match(err.message, /timed out/i)
|
|
|
|
assert.match(err.message, /15/i)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2022-01-21 02:43:48 +00:00
|
|
|
t.describe('Request download', function() {
|
|
|
|
const assertBody = `<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
</body>
|
|
|
|
</html>`
|
|
|
|
|
|
|
|
t.beforeEach(function() {
|
|
|
|
handler = defaultHandler
|
|
|
|
})
|
|
|
|
|
|
|
|
t.afterEach(function() {
|
|
|
|
return fs.rm(testTargetFile)
|
|
|
|
.catch(function() { })
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should support downloading file successfully', async function() {
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end(assertBody);
|
|
|
|
}
|
|
|
|
await request({}, prefix, testTargetFile)
|
|
|
|
|
|
|
|
let stat = await fs.stat(testTargetFile)
|
|
|
|
assert.notStrictEqual(stat.size, 0)
|
|
|
|
assert.strictEqual(stat.size, assertBody.length)
|
|
|
|
let contents = await (await fs.readFile(testTargetFile)).toString()
|
|
|
|
assert.strictEqual(contents, assertBody)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should support downloading file after redirect successfully', async function() {
|
|
|
|
let counter = 0
|
|
|
|
handler = function(req, res) {
|
|
|
|
if (counter < 3) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.setHeader('Location', encodeURI(prefix))
|
|
|
|
res.end();
|
|
|
|
counter++
|
|
|
|
return
|
|
|
|
}
|
|
|
|
res.statusCode = 200
|
|
|
|
res.end(assertBody);
|
|
|
|
}
|
|
|
|
await request({}, prefix, testTargetFile)
|
|
|
|
|
|
|
|
assert.strictEqual(counter, 3)
|
|
|
|
let stat = await fs.stat(testTargetFile)
|
|
|
|
assert.notStrictEqual(stat.size, 0)
|
|
|
|
assert.strictEqual(stat.size, assertBody.length)
|
|
|
|
let contents = await (await fs.readFile(testTargetFile)).toString()
|
|
|
|
assert.strictEqual(contents, assertBody)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should not create file if download redirects too many times', async function() {
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 302
|
|
|
|
res.setHeader('Location', encodeURI(prefix))
|
|
|
|
res.end(assertBody);
|
|
|
|
}
|
|
|
|
let err = await assert.isRejected(request({}, prefix, testTargetFile))
|
|
|
|
|
|
|
|
assert.match(err.message, /redirects/)
|
|
|
|
let errStat = await assert.isRejected(fs.stat(testTargetFile))
|
|
|
|
assert.strictEqual(errStat.code, 'ENOENT')
|
|
|
|
})
|
|
|
|
|
|
|
|
t.test('should not create file if download fails', async function() {
|
|
|
|
handler = function(req, res) {
|
|
|
|
res.statusCode = 404
|
|
|
|
res.end('{}');
|
|
|
|
}
|
|
|
|
let err = await assert.isRejected(request({}, prefix, testTargetFile))
|
|
|
|
|
|
|
|
assert.match(err.message, /HTTP/)
|
|
|
|
assert.match(err.message, /404/)
|
|
|
|
|
|
|
|
let errStat = await assert.isRejected(fs.stat(testTargetFile))
|
|
|
|
assert.strictEqual(errStat.code, 'ENOENT')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2022-01-11 16:51:15 +00:00
|
|
|
t.after(function(cb) {
|
|
|
|
server.close(cb)
|
|
|
|
})
|