import * as series from 'async/series'
import * as request from 'request'
import * as WebSocket from 'ws'
import { CONFIG } from '../server/initializers/constants'
const requestHeaders = {
'Range': '',
'Keep-Alive': '',
'User-Agent': 'Mozilla',
'Cache-Control': 'no-cache',
'Content-Type': '',
'Host': 'example.com',
'Access-Control-Request-Method': 'GET',
'Access-Control-Request-Headers': 'range'
}
series([
pingServer,
checkCORSTorrent,
checkCORSWebSeed,
checkTracker
], function () {
process.exit(0)
})
// ---------------------------------------------------------------------------
function pingServer (callback: () => void) {
const pingUrl = CONFIG.WEBSERVER.URL + '/api/v1/ping'
console.log('Checking server is up (%s)...', pingUrl)
request(pingUrl, function (err, res, body) {
if (!err && res.statusCode === 200 && body === 'pong') {
console.log('SUCCESS.')
} else {
console.log('FAIL.')
}
callback()
})
}
function checkCORSTorrent (callback: () => void) {
const torrentUrl = CONFIG.WEBSERVER.URL + '/static/torrents/test.torrent'
console.log('Checking CORS headers for the torrent (%s)...', torrentUrl)
request({
method: 'OPTIONS',
uri: torrentUrl,
headers: requestHeaders
}, function (err, res) {
if (err || isThereValidCORSHeaders(res) === false) {
console.error('FAIL.')
} else {
console.log('SUCCESS.')
}
callback()
})
}
function checkCORSWebSeed (callback: () => void) {
const webseedUrl = CONFIG.WEBSERVER.URL + '/static/webseed/test.mp4'
console.log('Checking CORS headers for the video (%s)...', webseedUrl)
request({
method: 'OPTIONS',
uri: webseedUrl,
headers: requestHeaders
}, function (err, res) {
if (err || isThereValidCORSHeaders(res) === false) {
console.error('FAIL.')
} else {
console.log('SUCCESS.')
}
callback()
})
}
function checkTracker (callback: () => void) {
const trackerUrl = CONFIG.WEBSERVER.WS + '://' +
CONFIG.WEBSERVER.HOST +
'/tracker/socket'
console.log('Checking tracker websocket (%s)...', trackerUrl)
let ws = null
ws = new WebSocket(trackerUrl)
const timeout = setTimeout(failed, 1000)
ws.on('open', onOpen)
function onOpen () {
clearTimeout(timeout)
ws.close()
console.log('SUCCESS.')
callback()
}
function failed () {
ws.removeListener('open', onOpen)
ws.close()
console.log('FAILED.')
callback()
}
}
function isThereValidCORSHeaders (res: request.RequestResponse) {
let fail = false
// Check Access-Control-Allow-Origin
const headerAllowOriginKey = 'access-control-allow-origin'
const headerAllowOrigin = res.headers[headerAllowOriginKey]
if (!headerAllowOrigin) {
console.error(headerAllowOriginKey + ' is not present.')
fail = true
} else if (headerAllowOrigin !== '*') {
console.error(headerAllowOriginKey + ' does not equal "*".')
fail = true
}
// Check Access-Control-Allow-Methods
const headerAllowMethodsKey = 'access-control-allow-methods'
const headerAllowMethods = res.headers[headerAllowMethodsKey]
if (!headerAllowMethods) {
console.error(headerAllowMethodsKey + ' is not present.')
fail = true
} else {
const allowMethodsMissed = findPatternNotInString(headerAllowMethods, [ 'get' ])
if (allowMethodsMissed !== null) {
console.error(headerAllowMethodsKey + ' misses the ' + allowMethodsMissed + ' method.')
fail = true
}
}
// Check Access-Control-Allow-Headers
const headerAllowHeadersKey = 'access-control-allow-headers'
const headerAllowHeaders = res.headers[headerAllowHeadersKey]
if (!headerAllowHeaders) {
console.error(headerAllowHeadersKey + ' is not present.')
fail = true
} else {
const headersThatShouldBePresent = [
'Range'
]
const allowHeadersMissed = findPatternNotInString(headerAllowHeaders, headersThatShouldBePresent)
if (allowHeadersMissed !== null) {
console.error(headerAllowHeadersKey + ' misses the ' + allowHeadersMissed + ' header.')
fail = true
}
}
return !fail
}
function findPatternNotInString (stringChain: string, patterns: string[]) {
let res = null
const stringChainLowerCase = stringChain.toLowerCase()
patterns.forEach(function (pattern) {
if (stringChainLowerCase.indexOf(pattern.toLowerCase()) === -1) {
res = pattern
}
})
return res
}