mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	Merge pull request #4162 from akhoury/master
add continuation-local-storage (CLS) support
This commit is contained in:
		| @@ -26,6 +26,7 @@ | ||||
|     "connect-mongo": "~1.1.0", | ||||
|     "connect-multiparty": "^2.0.0", | ||||
|     "connect-redis": "~3.0.2", | ||||
|     "continuation-local-storage": "^3.1.6", | ||||
|     "cookie-parser": "^1.3.3", | ||||
|     "cron": "^1.0.5", | ||||
|     "csurf": "^1.6.1", | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/middleware/cls.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/middleware/cls.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| var path = require('path'); | ||||
| var sockets = require('path'); | ||||
| var websockets = require('../socket.io/'); | ||||
| var continuationLocalStorage = require('continuation-local-storage'); | ||||
| var APP_NAMESPACE = require(path.join(__dirname, '../../package.json')).name; | ||||
| var namespace = continuationLocalStorage.createNamespace(APP_NAMESPACE); | ||||
|  | ||||
| (function(cls) { | ||||
| 	cls.http = function (req, res, next) { | ||||
| 		namespace.run(function() { | ||||
| 			namespace.set('request', req); | ||||
| 			next && next(); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	cls.socket = function (socket, payload, event, next) { | ||||
| 		namespace.run(function() { | ||||
| 			namespace.set('request', websockets.reqFromSocket(socket, payload, event)); | ||||
| 			next && next(); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	cls.get = function (key) { | ||||
| 		return namespace.get(key); | ||||
| 	}; | ||||
|  | ||||
| 	cls.set = function (key, value) { | ||||
| 		return namespace.set(key, value); | ||||
| 	}; | ||||
|  | ||||
| 	cls.setItem = cls.set; | ||||
| 	cls.getItem = cls.set; | ||||
| 	cls.namespace = namespace; | ||||
| 	cls.continuationLocalStorage = continuationLocalStorage; | ||||
|  | ||||
| })(exports); | ||||
|  | ||||
|  | ||||
| @@ -14,6 +14,7 @@ var meta = require('../meta'), | ||||
| 	compression = require('compression'), | ||||
| 	favicon = require('serve-favicon'), | ||||
| 	session = require('express-session'), | ||||
| 	cls = require('./cls'), | ||||
| 	useragent = require('express-useragent'); | ||||
|  | ||||
|  | ||||
| @@ -73,6 +74,7 @@ module.exports = function(app) { | ||||
|  | ||||
| 	app.use(middleware.addHeaders); | ||||
| 	app.use(middleware.processRender); | ||||
| 	app.use(cls.http); | ||||
| 	auth.initialize(app, middleware); | ||||
|  | ||||
| 	return middleware; | ||||
|   | ||||
| @@ -8,6 +8,28 @@ module.exports = function(Plugins) { | ||||
| 		'filter:user.custom_fields': null	// remove in v1.1.0 | ||||
| 	}; | ||||
|  | ||||
| 	Plugins.deprecatedHooksParams = { | ||||
| 		'action:homepage.get': '{req, res}', | ||||
| 		'filter:register.check': '{req, res}', | ||||
| 		'action:user.loggedOut': '{req, res}', | ||||
| 		'static:user.loggedOut': '{req, res}', | ||||
| 		'filter:categories.build': '{req, res}', | ||||
| 		'filter:category.build': '{req, res}', | ||||
| 		'filter:group.build': '{req, res}', | ||||
| 		'filter:register.build': '{req, res}', | ||||
| 		'filter:composer.build': '{req, res}', | ||||
| 		'filter:popular.build': '{req, res}', | ||||
| 		'filter:recent.build': '{req, res}', | ||||
| 		'filter:topic.build': '{req, res}', | ||||
| 		'filter:users.build': '{req, res}', | ||||
| 		'filter:admin.category.get': '{req, res}', | ||||
| 		'filter:middleware.renderHeader': '{req, res}', | ||||
| 		'filter:widget.render': '{req, res}', | ||||
| 		'filter:middleware.buildHeader': '{req, locals}', | ||||
| 		'action:middleware.pageView': '{req}', | ||||
| 		'action:meta.override404': '{req}' | ||||
| 	}; | ||||
|  | ||||
| 	/* | ||||
| 		`data` is an object consisting of (* is required): | ||||
| 			`data.hook`*, the name of the NodeBB hook | ||||
| @@ -33,6 +55,17 @@ module.exports = function(Plugins) { | ||||
| 					'there is no alternative.' | ||||
| 				) | ||||
| 			); | ||||
| 		} else { | ||||
| 			// handle hook's startsWith, i.e. action:homepage.get | ||||
| 			var _parts = data.hook.split(':'); | ||||
| 			_parts.pop(); | ||||
| 			var _hook = _parts.join(':'); | ||||
| 			if (Plugins.deprecatedHooksParams[_hook]) { | ||||
| 				winston.warn('[plugins/' + id + '] Hook `' + _hook + '` parameters: `' + Plugins.deprecatedHooksParams[_hook] + '`, are being deprecated, ' | ||||
| 				+ 'all plugins should now use the `middleware/cls` module instead of hook\'s arguments to get a reference to the `req`, `res` and/or `socket` object(s) (from which you can get the current `uid` if you need to.) ' | ||||
| 				+ '- for more info, visit https://docs.nodebb.org/en/latest/plugins/create.html#getting-a-reference-to-each-request-from-within-any-plugin-hook'); | ||||
| 				delete Plugins.deprecatedHooksParams[_hook]; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (data.hook && data.method) { | ||||
|   | ||||
| @@ -10,10 +10,10 @@ var winston = require('winston'); | ||||
| var db = require('../database'); | ||||
| var logger = require('../logger'); | ||||
| var ratelimit = require('../middleware/ratelimit'); | ||||
| var cls = require('../middleware/cls'); | ||||
|  | ||||
| var Sockets = {}; | ||||
| (function(Sockets) { | ||||
| 	var Namespaces = {}; | ||||
|  | ||||
| 	var io; | ||||
|  | ||||
| 	Sockets.init = function (server) { | ||||
| @@ -29,6 +29,7 @@ Sockets.init = function(server) { | ||||
| 		io.use(authorize); | ||||
|  | ||||
| 		io.on('connection', onConnection); | ||||
| 		io.on('disconnect', onDisconnect); | ||||
|  | ||||
| 		io.listen(server, { | ||||
| 			transports: nconf.get('socket.io:transports') | ||||
| @@ -42,11 +43,15 @@ function onConnection(socket) { | ||||
|  | ||||
| 		logger.io_one(socket, socket.uid); | ||||
|  | ||||
| 		cls.socket(socket, null, 'connection', function () { | ||||
| 			onConnect(socket); | ||||
| 		}); | ||||
|  | ||||
| 		socket.on('*', function (payload) { | ||||
| 			cls.socket(socket, payload, null, function () { | ||||
| 				onMessage(socket, payload); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	function onConnect(socket) { | ||||
| @@ -58,6 +63,11 @@ function onConnect(socket) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	function onDisconnect(socket) { | ||||
| 		cls.socket(socket, null, 'disconnect', function () { | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	function onMessage(socket, payload) { | ||||
| 		if (!payload.data.length) { | ||||
| @@ -66,7 +76,8 @@ function onMessage(socket, payload) { | ||||
|  | ||||
| 		var eventName = payload.data[0]; | ||||
| 		var params = payload.data[1]; | ||||
| 	var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function() {}; | ||||
| 		var callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function () { | ||||
| 		}; | ||||
|  | ||||
| 		if (!eventName) { | ||||
| 			return winston.warn('[socket.io] Empty method name'); | ||||
| @@ -198,12 +209,17 @@ Sockets.getUserSocketCount = function(uid) { | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| Sockets.reqFromSocket = function(socket) { | ||||
| 	Sockets.reqFromSocket = function (socket, payload, event) { | ||||
| 		var headers = socket.request.headers; | ||||
| 		var host = headers.host; | ||||
| 		var referer = headers.referer || ''; | ||||
| 		var data = ((payload || {}).data || []); | ||||
|  | ||||
| 		return { | ||||
| 			uid: socket.uid, | ||||
| 			params: data[1], | ||||
| 			method: event || data[0], | ||||
| 			body: payload, | ||||
| 			ip: headers['x-forwarded-for'] || socket.ip, | ||||
| 			host: host, | ||||
| 			protocol: socket.request.connection.encrypted ? 'https' : 'http', | ||||
| @@ -214,5 +230,4 @@ Sockets.reqFromSocket = function(socket) { | ||||
| 		}; | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| module.exports = Sockets; | ||||
| })(exports); | ||||
		Reference in New Issue
	
	Block a user