<commit_before>// Forked from Anvil's http host and other modules
// Copyright <NAME> 2011
// MIT License - http://opensource.org/licenses/MIT

var http = require( 'http' ),
	ServerResponse = require( 'http' ).ServerResponse,
	express = require( 'express' ),
	path = require( 'path' ),
	fs = require( 'fs' ),
	url = require( 'url' ),
	net = require ( 'net' ),
	_ = require( 'lodash' ),
	mkdirp = require( 'mkdirp' ),
	request = require( 'request' ),
	Monologue = require( 'monologue.js' )( _ ),
	watchTree = require( 'fs-watch-tree' ).watchTree,
	SocketStream = require( './socketStream' ),
	metrics = require( 'cluster-metrics' );

module.exports = function( config ) {
	var PREFIX = 'autohost';

	var Host = function() {
		this.clients = [];
		this.clients.lookup = {};
		this.compilers = {};
		this.middleware = [];
		this.config = config || {};
		this.topics = {};
		this.resources = {};
		this.actions = {};
		this.metrics = metrics;
		this.appName = this.config.appName || 'autohost';
		_.bindAll( this );
	};

	Host.prototype.addCompiler = function( extension, callback ) {
		this.compilers[ extension ] = callback;
		if( this.app ) {
			this.app.engine( extension, callback );
		}
	};

	Host.prototype.addMiddleware = function( filter, middleware ) {
		this.middleware.push( { filter: filter, handler: middleware } );
		if( this.app ) {
			this.app.use( filter, middleware );
		}
	};

	Host.prototype.buildPath = function( pathSpec ) {
		var hasLocalPrefix;
		pathSpec = pathSpec || '';
		if( _.isArray( pathSpec ) ) {
			hasLocalPrefix = pathSpec[0].match( /^[.]\// );
			pathSpec = path.join.apply( {}, pathSpec );
		}
		pathSpec = pathSpec.replace( /^~/, process.env.HOME );
		return hasLocalPrefix ? './' + pathSpec : pathSpec;
	};

	// yay, <NAME> to the rescue with this bit
	Host.prototype.buildUrl = function() {
		var idx = 0,
			cleaned = [];
		while( idx < arguments.length ) {
			var segment = arguments[ idx ];
			if( segment.substr( 0, 1 ) === '/' ) {
				segment = segment.substr( 1 );
			}
			if( segment.substr( segment.length-1, 1 ) === '/' ) {
				segment = segment.substring( 0, segment.length - 1 );
			}
			if( !_.isEmpty( segment ) ) {
				cleaned.push( segment );
			}
			idx++;
		}
		return '/' + cleaned.join( '/' );
	};

	Host.prototype.handleRoute = function( url, verb, resource, handle, action ) {
		this.registerRoute( url, verb, function( req, res ) {
			var respond = function() {
				var envelope = {
					context: req.context,
					data: req.body,
					path: req.url,
					headers: req.headers,
					params: {},
					files: req.files,
					user: req.user,
					responseStream: res,
					forwardTo: function( options ) {
						return req.pipe( request( options ) );
					},
					reply: function( envelope ) {
						var code = envelope.statusCode || 200;
						res.send( code, envelope.data );
					},
					replyWithFile: function(envelope, contentType, sendFileName, sendStream) {
						res.set({
							"Content-Disposition": 'attachment; filename="'+sendFileName+'"',
							"Content-Type": contentType
						});
						sendStream.pipe(res);
					}
				};
				for( var key in req.params ) {
					var val = req.params[ key ];
					if( !envelope.data[ key ] ) {
						envelope.data[ key ] = val;
					}
					envelope.params[ key ] = val;
				}
				for( var key in req.query ) {
					var val = req.query[ key ];
					if( !envelope.data[ key ] ) {
						envelope.data[ key ] = val;
					}
					envelope.params[ key ] = val;
				}
				handle.apply( resource, [ envelope ] );
			};

			if( this.authorizer ) {
				this.authorizer.getRolesFor( action, function( err, roles ) {
					roles = err ? [] : roles;

					if( roles.length > 0 && _.intersection( roles, req.user.roles ) == 0 ) {
						res.send( 403, "User lacks sufficient permissions" );
					} else {
						respond();
					}
				} );
			} else {
				respond();
			}
		}.bind( this ) );
	};

	Host.prototype.handleTopic = function( topic, resource, handle, action ) {
		this.registerTopic( topic, function( message, socket ) {
			var respond = function() {
				var envelope = {
					data: message.data || message,
					headers: message.headers || [],
					socket: socket,
					user: socket.user,
					path: message.topic,
					reply: function( envelope ) {
						socket.publish( message.replyTo, envelope );
					},
					responseStream: new SocketStream( message.replyTo, socket )
				};
				handle.apply( resource, [ envelope ] );
			};
		
			if( this.authorizer ) {
				this.authorizer.getRolesFor( action, function( err, roles ) {
					roles = err ? [] : roles;
					if( roles.length > 0 && _.intersection( roles, socket.user.roles ) == 0 ) {
						socket.publish( 'NoPe', 'User lacks sufficient permissions' );
					} else {
						respond();
					}
				} );	
			} else {
				respond();
			}
		}.bind( this ) );
	};

	Host.prototype.init = function( config, done ) {
		if( config ) {
			this.config = _.merge( this.config, config );
		}
		var self = this,
			cwd = process.cwd(),
			tmp = path.resolve( cwd, ( this.config.temp || './tmp' ) ),
			public = path.resolve( cwd, ( this.config.static || './public' ) ),
			resources = path.resolve( cwd, ( this.config.resources || './resource' ) );

		mkdirp( tmp );

		this.app = express();
		this.app.use( '/', function( req, res, next ) {
			var timerKey = [ req.method.toUpperCase(), req.url, 'timer' ].join( ' ' );
			metrics.timer( timerKey ).start();<commit_msg>Add a context property to the request object in middleware<commit_after>// Forked from Anvil's http host and other modules
// Copyright <NAME> 2011
// MIT License - http://opensource.org/licenses/MIT

var http = require( 'http' ),
	ServerResponse = require( 'http' ).ServerResponse,
	express = require( 'express' ),
	path = require( 'path' ),
	fs = require( 'fs' ),
	url = require( 'url' ),
	net = require ( 'net' ),
	_ = require( 'lodash' ),
	mkdirp = require( 'mkdirp' ),
	request = require( 'request' ),
	Monologue = require( 'monologue.js' )( _ ),
	watchTree = require( 'fs-watch-tree' ).watchTree,
	SocketStream = require( './socketStream' ),
	metrics = require( 'cluster-metrics' );

module.exports = function( config ) {
	var PREFIX = 'autohost';

	var Host = function() {
		this.clients = [];
		this.clients.lookup = {};
		this.compilers = {};
		this.middleware = [];
		this.config = config || {};
		this.topics = {};
		this.resources = {};
		this.actions = {};
		this.metrics = metrics;
		this.appName = this.config.appName || 'autohost';
		_.bindAll( this );
	};

	Host.prototype.addCompiler = function( extension, callback ) {
		this.compilers[ extension ] = callback;
		if( this.app ) {
			this.app.engine( extension, callback );
		}
	};

	Host.prototype.addMiddleware = function( filter, middleware ) {
		this.middleware.push( { filter: filter, handler: middleware } );
		if( this.app ) {
			this.app.use( filter, middleware );
		}
	};

	Host.prototype.buildPath = function( pathSpec ) {
		var hasLocalPrefix;
		pathSpec = pathSpec || '';
		if( _.isArray( pathSpec ) ) {
			hasLocalPrefix = pathSpec[0].match( /^[.]\// );
			pathSpec = path.join.apply( {}, pathSpec );
		}
		pathSpec = pathSpec.replace( /^~/, process.env.HOME );
		return hasLocalPrefix ? './' + pathSpec : pathSpec;
	};

	// yay, <NAME> to the rescue with this bit
	Host.prototype.buildUrl = function() {
		var idx = 0,
			cleaned = [];
		while( idx < arguments.length ) {
			var segment = arguments[ idx ];
			if( segment.substr( 0, 1 ) === '/' ) {
				segment = segment.substr( 1 );
			}
			if( segment.substr( segment.length-1, 1 ) === '/' ) {
				segment = segment.substring( 0, segment.length - 1 );
			}
			if( !_.isEmpty( segment ) ) {
				cleaned.push( segment );
			}
			idx++;
		}
		return '/' + cleaned.join( '/' );
	};

	Host.prototype.handleRoute = function( url, verb, resource, handle, action ) {
		this.registerRoute( url, verb, function( req, res ) {
			var respond = function() {
				var envelope = {
					context: req.context,
					data: req.body,
					path: req.url,
					headers: req.headers,
					params: {},
					files: req.files,
					user: req.user,
					responseStream: res,
					forwardTo: function( options ) {
						return req.pipe( request( options ) );
					},
					reply: function( envelope ) {
						var code = envelope.statusCode || 200;
						res.send( code, envelope.data );
					},
					replyWithFile: function(envelope, contentType, sendFileName, sendStream) {
						res.set({
							"Content-Disposition": 'attachment; filename="'+sendFileName+'"',
							"Content-Type": contentType
						});
						sendStream.pipe(res);
					}
				};
				for( var key in req.params ) {
					var val = req.params[ key ];
					if( !envelope.data[ key ] ) {
						envelope.data[ key ] = val;
					}
					envelope.params[ key ] = val;
				}
				for( var key in req.query ) {
					var val = req.query[ key ];
					if( !envelope.data[ key ] ) {
						envelope.data[ key ] = val;
					}
					envelope.params[ key ] = val;
				}
				handle.apply( resource, [ envelope ] );
			};

			if( this.authorizer ) {
				this.authorizer.getRolesFor( action, function( err, roles ) {
					roles = err ? [] : roles;

					if( roles.length > 0 && _.intersection( roles, req.user.roles ) == 0 ) {
						res.send( 403, "User lacks sufficient permissions" );
					} else {
						respond();
					}
				} );
			} else {
				respond();
			}
		}.bind( this ) );
	};

	Host.prototype.handleTopic = function( topic, resource, handle, action ) {
		this.registerTopic( topic, function( message, socket ) {
			var respond = function() {
				var envelope = {
					data: message.data || message,
					headers: message.headers || [],
					socket: socket,
					user: socket.user,
					path: message.topic,
					reply: function( envelope ) {
						socket.publish( message.replyTo, envelope );
					},
					responseStream: new SocketStream( message.replyTo, socket )
				};
				handle.apply( resource, [ envelope ] );
			};
		
			if( this.authorizer ) {
				this.authorizer.getRolesFor( action, function( err, roles ) {
					roles = err ? [] : roles;
					if( roles.length > 0 && _.intersection( roles, socket.user.roles ) == 0 ) {
						socket.publish( 'NoPe', 'User lacks sufficient permissions' );
					} else {
						respond();
					}
				} );	
			} else {
				respond();
			}
		}.bind( this ) );
	};

	Host.prototype.init = function( config, done ) {
		if( config ) {
			this.config = _.merge( this.config, config );
		}
		var self = this,
			cwd = process.cwd(),
			tmp = path.resolve( cwd, ( this.config.temp || './tmp' ) ),
			public = path.resolve( cwd, ( this.config.static || './public' ) ),
			resources = path.resolve( cwd, ( this.config.resources || './resource' ) );

		mkdirp( tmp );

		this.app = express();
		this.app.use( '/', function( req, res, next ) {
			req.context = {};
			var timerKey = [ req.method.toUpperCase(), req.url, 'timer' ].join( ' ' );
			metrics.timer( timerKey ).start();
{'fraction_non_alphanumeric': 0.16651359294636298, 'fraction_numerical': 0.004224834680382072, 'mean_word_length': 2.665095927297206, 'pattern_counts': {'":': 4, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5747778', 'n_tokens_mistral': 4392, 'n_tokens_neox': 3539, 'n_words': 859}