diff options
-rw-r--r-- | package.json | 6 | ||||
-rwxr-xr-x | scripts/check.js | 174 | ||||
-rwxr-xr-x | scripts/help.sh | 1 | ||||
-rw-r--r-- | server/controllers/api/v1/index.js | 5 |
4 files changed, 185 insertions, 1 deletions
diff --git a/package.json b/package.json index 1111c7a6d..8e2163bb2 100644 --- a/package.json +++ b/package.json | |||
@@ -5,7 +5,7 @@ | |||
5 | "private": true, | 5 | "private": true, |
6 | "licence": "GPLv3", | 6 | "licence": "GPLv3", |
7 | "engines": { | 7 | "engines": { |
8 | "node": ">=4.2.0" | 8 | "node": ">=4.x" |
9 | }, | 9 | }, |
10 | "author": { | 10 | "author": { |
11 | "name": "Florian Bigard", | 11 | "name": "Florian Bigard", |
@@ -30,6 +30,7 @@ | |||
30 | "play": "scripty", | 30 | "play": "scripty", |
31 | "dev": "scripty", | 31 | "dev": "scripty", |
32 | "start": "node server", | 32 | "start": "node server", |
33 | "check": "scripty", | ||
33 | "test": "scripty", | 34 | "test": "scripty", |
34 | "help": "scripty", | 35 | "help": "scripty", |
35 | "postinstall": "cd client && npm install" | 36 | "postinstall": "cd client && npm install" |
@@ -90,5 +91,8 @@ | |||
90 | "describe", | 91 | "describe", |
91 | "include" | 92 | "include" |
92 | ] | 93 | ] |
94 | }, | ||
95 | "scripty": { | ||
96 | "silent": true | ||
93 | } | 97 | } |
94 | } | 98 | } |
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 | } | ||
diff --git a/scripts/help.sh b/scripts/help.sh index 6e124c276..fdccabbf0 100755 --- a/scripts/help.sh +++ b/scripts/help.sh | |||
@@ -15,5 +15,6 @@ printf " danger:clean:modules -> /!\ Clean node and typescript modules\n" | |||
15 | printf " play -> Run 3 fresh nodes so that you can test the communication between them\n" | 15 | printf " play -> Run 3 fresh nodes so that you can test the communication between them\n" |
16 | printf " dev -> Watch, run the livereload and run the server so that you can develop the application\n" | 16 | printf " dev -> Watch, run the livereload and run the server so that you can develop the application\n" |
17 | printf " start -> Run the server\n" | 17 | printf " start -> Run the server\n" |
18 | printf " check -> Check the server (according to NODE_ENV)\n" | ||
18 | printf " test -> Run the tests\n" | 19 | printf " test -> Run the tests\n" |
19 | printf " help -> Print this help\n" | 20 | printf " help -> Print this help\n" |
diff --git a/server/controllers/api/v1/index.js b/server/controllers/api/v1/index.js index 2e4fb2dab..4cb65ed55 100644 --- a/server/controllers/api/v1/index.js +++ b/server/controllers/api/v1/index.js | |||
@@ -17,6 +17,7 @@ router.use('/remote', remoteController) | |||
17 | router.use('/requests', requestsController) | 17 | router.use('/requests', requestsController) |
18 | router.use('/users', usersController) | 18 | router.use('/users', usersController) |
19 | router.use('/videos', videosController) | 19 | router.use('/videos', videosController) |
20 | router.use('/ping', pong) | ||
20 | router.use('/*', badRequest) | 21 | router.use('/*', badRequest) |
21 | 22 | ||
22 | // --------------------------------------------------------------------------- | 23 | // --------------------------------------------------------------------------- |
@@ -25,6 +26,10 @@ module.exports = router | |||
25 | 26 | ||
26 | // --------------------------------------------------------------------------- | 27 | // --------------------------------------------------------------------------- |
27 | 28 | ||
29 | function pong (req, res, next) { | ||
30 | return res.send('pong').status(200).end() | ||
31 | } | ||
32 | |||
28 | function badRequest (req, res, next) { | 33 | function badRequest (req, res, next) { |
29 | res.type('json').status(400).end() | 34 | res.type('json').status(400).end() |
30 | } | 35 | } |