diff options
Diffstat (limited to 'scripts/check.js')
-rwxr-xr-x | scripts/check.js | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/scripts/check.js b/scripts/check.js new file mode 100755 index 000000000..5e9e4cabf --- /dev/null +++ b/scripts/check.js | |||
@@ -0,0 +1,174 @@ | |||
1 | #!/bin/env node | ||
2 | |||
3 | 'use strict' | ||
4 | |||
5 | const series = require('async/series') | ||
6 | const request = require('request') | ||
7 | const WebSocket = require('ws') | ||
8 | |||
9 | const constants = require('../server/initializers/constants') | ||
10 | const requestHeaders = { | ||
11 | 'Range': '', | ||
12 | 'Keep-Alive': '', | ||
13 | 'User-Agent': 'Mozilla', | ||
14 | 'Cache-Control': 'no-cache', | ||
15 | 'Content-Type': '', | ||
16 | 'Host': 'example.com', | ||
17 | 'Access-Control-Request-Method': 'GET', | ||
18 | 'Access-Control-Request-Headers': 'range' | ||
19 | } | ||
20 | |||
21 | series([ | ||
22 | pingServer, | ||
23 | checkCORSTorrent, | ||
24 | checkCORSWebSeed, | ||
25 | checkTracker | ||
26 | ], function () { | ||
27 | process.exit(0) | ||
28 | }) | ||
29 | |||
30 | // --------------------------------------------------------------------------- | ||
31 | |||
32 | function pingServer (callback) { | ||
33 | const pingUrl = constants.CONFIG.WEBSERVER.URL + '/api/v1/ping' | ||
34 | console.log('Checking server is up (%s)...', pingUrl) | ||
35 | |||
36 | request(pingUrl, function (err, res, body) { | ||
37 | if (!err && res.statusCode === 200 && body === 'pong') { | ||
38 | console.log('SUCCESS.') | ||
39 | } else { | ||
40 | console.log('FAIL.') | ||
41 | } | ||
42 | |||
43 | callback() | ||
44 | }) | ||
45 | } | ||
46 | |||
47 | function checkCORSTorrent (callback) { | ||
48 | const torrentUrl = constants.CONFIG.WEBSERVER.URL + '/static/torrents/test.torrent' | ||
49 | console.log('Checking CORS headers for the torrent (%s)...', torrentUrl) | ||
50 | |||
51 | request({ | ||
52 | method: 'OPTIONS', | ||
53 | uri: torrentUrl, | ||
54 | headers: requestHeaders | ||
55 | }, function (err, res) { | ||
56 | if (err || isThereValidCORSHeaders(res) === false) { | ||
57 | console.error('FAIL.') | ||
58 | } else { | ||
59 | console.log('SUCCESS.') | ||
60 | } | ||
61 | |||
62 | callback() | ||
63 | }) | ||
64 | } | ||
65 | |||
66 | function checkCORSWebSeed (callback) { | ||
67 | const webseedUrl = constants.CONFIG.WEBSERVER.URL + '/static/webseed/test.mp4' | ||
68 | console.log('Checking CORS headers for the video (%s)...', webseedUrl) | ||
69 | |||
70 | request({ | ||
71 | method: 'OPTIONS', | ||
72 | uri: webseedUrl, | ||
73 | headers: requestHeaders | ||
74 | }, function (err, res) { | ||
75 | if (err || isThereValidCORSHeaders(res) === false) { | ||
76 | console.error('FAIL.') | ||
77 | } else { | ||
78 | console.log('SUCCESS.') | ||
79 | } | ||
80 | |||
81 | callback() | ||
82 | }) | ||
83 | } | ||
84 | |||
85 | function checkTracker (callback) { | ||
86 | const trackerUrl = constants.CONFIG.WEBSERVER.WS + '://' + | ||
87 | constants.CONFIG.WEBSERVER.HOST + ':' + | ||
88 | constants.CONFIG.WEBSERVER.PORT + '/tracker/socket' | ||
89 | console.log('Checking tracker websocket (%s)...', trackerUrl) | ||
90 | |||
91 | let ws = null | ||
92 | ws = new WebSocket(trackerUrl) | ||
93 | |||
94 | const timeout = setTimeout(failed, 1000) | ||
95 | ws.on('open', onOpen) | ||
96 | |||
97 | function onOpen () { | ||
98 | clearTimeout(timeout) | ||
99 | ws.close() | ||
100 | |||
101 | console.log('SUCCESS.') | ||
102 | callback() | ||
103 | } | ||
104 | |||
105 | function failed () { | ||
106 | ws.removeListener('open', onOpen) | ||
107 | ws.close() | ||
108 | |||
109 | console.log('FAILED.') | ||
110 | callback() | ||
111 | } | ||
112 | } | ||
113 | |||
114 | function isThereValidCORSHeaders (res) { | ||
115 | let fail = false | ||
116 | |||
117 | // Check Access-Control-Allow-Origin | ||
118 | const headerAllowOriginKey = 'access-control-allow-origin' | ||
119 | const headerAllowOrigin = res.headers[headerAllowOriginKey] | ||
120 | |||
121 | if (!headerAllowOrigin) { | ||
122 | console.error(headerAllowOriginKey + ' is not present.') | ||
123 | fail = true | ||
124 | } else if (headerAllowOrigin !== '*') { | ||
125 | console.error(headerAllowOriginKey + ' does not equal "*".') | ||
126 | fail = true | ||
127 | } | ||
128 | |||
129 | // Check Access-Control-Allow-Methods | ||
130 | const headerAllowMethodsKey = 'access-control-allow-methods' | ||
131 | const headerAllowMethods = res.headers[headerAllowMethodsKey] | ||
132 | if (!headerAllowMethods) { | ||
133 | console.error(headerAllowMethodsKey + ' is not present.') | ||
134 | fail = true | ||
135 | } else { | ||
136 | const allowMethodsMissed = findPatternNotInString(headerAllowMethods, [ 'get' ]) | ||
137 | if (allowMethodsMissed !== null) { | ||
138 | console.error(headerAllowMethodsKey + ' misses the ' + allowMethodsMissed + ' method.') | ||
139 | fail = true | ||
140 | } | ||
141 | } | ||
142 | |||
143 | // Check Access-Control-Allow-Headers | ||
144 | const headerAllowHeadersKey = 'access-control-allow-headers' | ||
145 | const headerAllowHeaders = res.headers[headerAllowHeadersKey] | ||
146 | if (!headerAllowHeaders) { | ||
147 | console.error(headerAllowHeadersKey + ' is not present.') | ||
148 | fail = true | ||
149 | } else { | ||
150 | const headersThatShouldBePresent = [ | ||
151 | 'Range' | ||
152 | ] | ||
153 | const allowHeadersMissed = findPatternNotInString(headerAllowHeaders, headersThatShouldBePresent) | ||
154 | if (allowHeadersMissed !== null) { | ||
155 | console.error(headerAllowHeadersKey + ' misses the ' + allowHeadersMissed + ' header.') | ||
156 | fail = true | ||
157 | } | ||
158 | } | ||
159 | |||
160 | return !fail | ||
161 | } | ||
162 | |||
163 | function findPatternNotInString (stringChain, patterns) { | ||
164 | let res = null | ||
165 | const stringChainLowerCase = stringChain.toLowerCase() | ||
166 | |||
167 | patterns.forEach(function (pattern) { | ||
168 | if (stringChainLowerCase.indexOf(pattern.toLowerCase()) === -1) { | ||
169 | res = pattern | ||
170 | } | ||
171 | }) | ||
172 | |||
173 | return res | ||
174 | } | ||