]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/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 | '/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 | } |