Node.js помогите найти логические ошибки
#38049603
Ссылка:
Ссылка на сообщение:
Ссылка с названием темы:
|
|
|
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251. 252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265. 266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279. 280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293. 294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307. 308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321. 322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335. 336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349. 350. 351. 352. 353.
var KB = 1024;
var MB = 1048576;
var GB = 1073741824;
var SECOND = 1000;
var MINUTE = 60000;
var HOUR = 3600000;
var DAY = 86400000;
var WEEK = 604800000;
var MONTH = 2628000000;
var YEAR = 31536000000;
// добавляем свои
var ALLOWED_METHODS = ['GET', 'POST'];
var LISTEN_PORT = 8080;
var STATIC_FILES_DIRECTORY = './public';
var MAX_REQUEST_LENGTH = 4 * MB;
var http = require('http');
var fs = require('fs');
var qs = require('querystring');
var url = require('url');
var path = require('path');
var crypto = require('crypto');
var util = require('util');
var passwords = {tester: 'test', noob: 'qwe123'}
//=======================================================================================
// задаем пути
// rq экземпляр обьекта http.IncomingMessage
// rs экземпляр обьекта http.ServerResponse
// rq.url /path?query
// rq.path декодированный путь
// rq.query {[key: value[, key1: value1[], ...]]}
// rq.body тело запроса буффер либо обьект(application/x-www-form-urlencoded)
// rq.cookie полученные куки в виде обьекта
// rq.session сессионные переменные
// rq.setCookie(name, value[, expires[, path[, domain[, secure[, httponly]]]]]);
// rq.removeCookie(name);
// session экземпляр обьекта Session
// session.init(rq, rs); инициализация сессии
// session.start(); делает доступным rq.session
// session.destroy(); уничтожить текущую сессию
var routes = {
GET: [
['/', function(rq, rs) {
session.start();
rs.writeHead(202, {'content-type': 'text/html; charset=utf-8'});
var out = '<!DOCTYPE html><head><meta charset="utf-8"></head><body>';
// не авторизован
if (!rq.session.username) {
out += '<form action="/login" method="post">' +
'<p><input name="username" placeholder="Введите имя">' +
'<p><input name="password" type="password" placeholder="Введите пароль">\n' +
'<p><input type="submit"></form>';
}
else {
out += '<p>Привет, ' + rq.session.username + '. <a href="/logout">Выйти</a></p>';
}
rs.end(out + '</body></html>');
}],
['/index.htm', function(rq, rs) {
rs.writeHead(302, {location: '/'})
rs.end();
}],
['/logout', function(rq, rs) {
session.destroy();
rs.writeHead(302, {location: '/'})
rs.end();
}]
],
POST: [
['/login', function(rq, rs) {
session.start();
rs.writeHead(202, {'content-type': 'text/html; charset=utf-8'});
var out = '<!DOCTYPE html><head><meta charset="utf-8"><meta http-equiv="refresh" content="3; URL=/"></head><body><p>';
if (rq.body.username && rq.body.password && rq.body.password === passwords[rq.body.username]) {
rq.session.username = rq.body.username;
out += 'Вы авторизовались'
}
else {
out += 'Неправильное имя или пароль';
}
rs.end(out + '<p></body></html>');
}],
]
};
//=======================================================================================
// mime
// var fs = require('fs');
// var path = require('path');
//
// module.exports = new function() {
var mime = new function() {
// используется от Apache
var MIME_TYPES_FILENAME = './mime.types';
var DEFAULT_MIME_TYPE = '*'; // application/octet-stream
var types = {};
var extensions = {};
var content = fs.readFileSync(MIME_TYPES_FILENAME, 'ascii');
var pos = 0;
var start = 0;
while ((pos = content.indexOf('\n', start)) > -1) {
var line = content.substr(start, pos - start);
// удаляем комментарии и пробелы на концах строки
line = line.replace(/#.*/, '');
line = line.trim();
if (line) {
var fields = line.split(/\t+|\s+/);
var type = fields.shift();
extensions[type] = fields[0];
var extension;
var i = 0;
while (extension = fields[i++]) {
types[extension] = type;
}
}
start = pos + 1;
}
// mime.getTypeByExtension('.ext');
this.getTypeByExtension = function(extension) {
extension = extension.split('.')[1];
return extension && types[extension] ? types[extension] : DEFAULT_MIME_TYPE;
}
// mime.getTypeByFilename('path/to/file.ext');
this.getTypeByFilename = function(filename) {
return this.getTypeByExtension(path.extname(filename));
}
// mime.getExtensionByType('type/subtype');
this.getExtensionByType = function(type) {
return extensions[type] ? '.' + extensions[type] : '';
}
}; // ошибка без ';'
// var mime = require('./mime');
//=======================================================================================
// куки
(function() {
// ServerRequest является объектом IncomingMessage
var rq = http.IncomingMessage.prototype;
var rs = http.ServerResponse.prototype;
Object.defineProperty(rq, 'cookie', {
get: function() {
// если не свойство не обьявленно парсим
if (this._cookie === undefined) {
this._cookie = qs.parse(this.headers['cookie'], '; ');
}
return this._cookie;
}
});
rs.setCookie = function(name, value, expires, path, domain, secure, httponly) {
var cookies = this.getHeader('set-cookie');
if (cookies === undefined) {
cookies = [];
}
else if (typeof cookies == 'string') {
cookies = [].concat(cookies);
}
cookies.push(name + '=' + qs.escape(value) +
(expires === undefined ? '' : '; Expires=' + new Date(expires).toUTCString()) +
(path ? '; Path=' + path : '') + (domain ? '; Domain=' + domain : '') +
(secure ? '; Secure' : '') + (httponly ? '; HttpOnly' : ''));
this.setHeader('set-cookie', cookies);
}
rs.removeCookie = function(name, path, domain) {
this.setCookie(name, '', 0, path, domain);
}
})();
//=======================================================================================
// сессии
function Session(name) {
name = name || 'sessid';
var SESSION_EXPIRES = 5 * MINUTE;
var storage = {};
var rq, rs;
this.init = function(serverRequest, serverResponse) {
console.log(storage);
rq = serverRequest;
rs = serverResponse;
console.log('session initializated');
}
this.start = function() {
// удаляем устаревшие сессии
for (var i in storage) {
if (storage[i].expires < new Date().getTime()) {
delete storage[i];
}
}
var key = rq.cookie[name];
var expires = new Date().getTime() + SESSION_EXPIRES;
// сессия еще не создана либо устарела
if (!key || !storage[key]) {
// вероятность совпадения хешей стремится к нулю, но все же
do {
key = crypto.createHash('md5').
update(rq.connection.remoteAddress + new Date().getTime()).
digest('hex');
} while (storage[key]);
storage[key] = {};
storage[key].data = {};
storage[key].expires = expires;
console.log('session created');
}
rq.session = storage[key].data;
rs.setCookie(name, key, expires);
console.log(name, '=', key);
}
this.destroy = function() {
delete storage[rq.cookie[name]];
console.log('session destroyed');
}
}
var session = new Session();
//=======================================================================================
// запускаем сервак
var server = http.createServer(function(rq, rs) {
// метод не поддерживается, отсылаем заголовки ничего не выводим
if (ALLOWED_METHODS.indexOf(rq.method) == -1) {
rq.pause();
rs.writeHead(405);
return rs.end();
}
console.log(rq.url);
var urlObj = url.parse(rq.url);
rq.path = qs.unescape(urlObj.pathname);
rq.query = urlObj.query;
// ищем обработчик пути
var runRoute;
if (routes[rq.method]) {
var subroutes = routes[rq.method];
var route;
var i = 0;
while (route = subroutes[i++]) {
if (route[0] instanceof RegExp) {
var matches = rq.path.match(route[0]);
if (matches) {
runRoute = function() {
route[1].apply(null, [rq, rs].concat(matches.slice(1)))
}
break;
}
}
else if (route[0] === rq.path) {
runRoute = function() {
route[1](rq, rs);
}
break;
}
}
}
// если его нет отдаем статику
if (!runRoute) {
rq.pause();
console.log('serve static files');
var filename = STATIC_FILES_DIRECTORY + rq.path;
fs.exists(filename, function(exists) {
if (!exists) {
rs.writeHead(404);
rs.end('404 Not Found\n');
return;
}
fs.readFile(filename, function(err, content) {
if (err) {
// файл является директорией или ???
rs.writeHead(500);
rs.end('500 Internal Server Error\n');
return;
}
rs.writeHead(200, {'content-type': mime.getTypeByFilename(filename)});
rs.end(content);
});
});
// вышли
return;
}
var requestLength = rq.headers['content-length'] > MAX_REQUEST_LENGTH ? MAX_REQUEST_LENGTH : 0;
rq.body = [];
rq.on('data', function(chunk) {
requestLength += chunk.length;
if (requestLength > MAX_REQUEST_LENGTH) {
console.log('maximum request length exceeded');
// ждем когда сборщик мусора убьёт поток
rq.pause();
rs.writeHead(413);
return rs.end();
}
this.body.push(chunk);
});
// ждем пока клиент не закончит передачу данных
rq.on('end', function() {
console.log('bytes received ' + requestLength);
this.body = Buffer.concat(this.body);
if (this.method == 'POST' && this.headers['content-type'] == 'application/x-www-form-urlencoded') {
this.body = qs.parse(this.body.toString());
}
this.isXhr = this.headers['x-requested-with'] == 'XMLHttpRequest';
// инициализируем механизм сессий
session.init(this, rs);
// вызываем обработчик
runRoute();
});
});
server.listen(LISTEN_PORT);
console.log('server was started');
|
|