<commit_before>'use strict';

var express = require('express'),
	constants = require('./../config/constants'),
	config = require('./../config/config'),
	repository = require('./../util/repository'),
	bugsense = require('./../util/bugsense'),
	middleware = require('./../scripts'),
	router = express.Router(),
	http = require('http'),
	https = require('https'),
	extend = require('extend'),
	querystring = require('querystring'),
	path = '/:domain/*';

router
	.use(path, middleware.domain) // verifies that domain is valid
	.use(path, middleware.options) // creates options options to be used for proxy request
	.use(path, middleware.reverse) // reverses accept and content-type headers
	.use(path, middleware.user) // handle special case of /users/ requests
	.use(path, function(req, res){
		// Make the proxy HTTP request
		var proxy_scheme = req.options.port === 443 ? https : http;

		// make proxy request
		var _updateAccessToken = function(oldAT, newAT, obj){
			// add semantic version number:
			obj.version = constants.TOKEN_STORAGE_VERSION;

			// delete old access token, if it exists
			repository.del(oldAT);

			// set the access/refresh token in the key/value store
			repository.set(newAT, JSON.stringify(obj));
		};

		/**
		 * Will parse the response for the website by setting the headers, handling cookies etc.
		 * Notice: This method will sends data back to the website
		 * @param proxy_response The response object
		 * @private
		 */
		var _parseResponse = function(proxy_response){
			if(res.headersSent){
				return;
			}
			var chunked = proxy_response.headers['transfer-encoding'] === 'chunked';

			var response_headers = {};
			// copy accross headers from proxy response to response
			for (var header in proxy_response.headers) {
				response_headers[header] = proxy_response.headers[header];
			}

			// transform API services content-type to application/json
			if (proxy_response.headers.hasOwnProperty('content-type')) {
				if (proxy_response.headers['content-type'].indexOf(constants.BBB_CONTENT_TYPE) === 0) {
					response_headers['content-type'] = 'application/json';
				}
			}
			// set status code if chunked
			if(chunked){
				res.writeHead(proxy_response.statusCode, response_headers);
			} else {
				for(var index in response_headers){
					res.setHeader(index, response_headers[index]);
				}
				res.status(proxy_response.statusCode);
			}
			var response_body;
			proxy_response.on('data', function (chunk) {
				if (!chunked) {
					response_body = chunk;
				} else {
					res.write(chunk);
				}
			});

			proxy_response.on('end', function() {
				if (!chunked) {
					// If appropriate, translate the authentication OAuth2 bearer token back to a cookie
					if ((req.options.path.indexOf(constants.AUTH_PATH_COMPONENT) !== -1 || req.options.path.indexOf(constants.AUTH_USERS_PATH) !== -1) &&
						proxy_response.headers.hasOwnProperty('content-type') &&
						proxy_response.headers['content-type'].indexOf('application/json') === 0) {
						try {
							var json_response = JSON.parse(String(response_body)),
									old_access_token,
									access_token,
									refresh_token,
									user_id_parts,
									user_id,
									body,
									remember_me,
									expires,
									expiresDate,
									writeResponse;
							if (json_response.hasOwnProperty(constants.AUTH_ACCESS_TOKEN_NAME)) {
								writeResponse = function () {
									// save new access token
									_updateAccessToken(old_access_token, access_token, {
										refresh_token: refresh_token,
										user_id: user_id,
										expires: expires
									});

									res.cookie(constants.AUTH_ACCESS_TOKEN_NAME, access_token, { path: '/api', expires: expiresDate, httpOnly: true, secure: true });

									// Strip the access and refresh tokens from the response body:
									delete json_response[constants.AUTH_REFRESH_TOKEN_NAME];
									delete json_response[constants.AUTH_ACCESS_TOKEN_NAME];

									response_body = JSON.stringify(json_response);
									res.setHeader('Content-Length', Buffer.byteLength(response_body));
									res.write(response_body);
									res.end();
								};

								// response is a refresh token request to the /oauth/token endpoint
								old_access_token = req.cookies[constants.AUTH_ACCESS_TOKEN_NAME];
								access_token = json_response[constants.AUTH_ACCESS_TOKEN_NAME];
								refresh_token = json_response[constants.AUTH_REFRESH_TOKEN_NAME];

								// get the user id from the response
								user_id_parts = json_response.user_id.split(':');
								user_id = user_id_parts[user_id_parts.length - 1];

								body = querystring.parse(req.body) || {};

								remember_me = body[constants.AUTH_PARAM_REMEMBER_ME] === 'true';

								if (!remember_me && !!old_access_token) {
									// Retrieve the expires value stored for the old access token:
									repository.get(old_access_token).then(function (value) {
										try {
											expires = JSON.parse(value).expires;
											expiresDate = expires ? new Date(expires) : null;
										} catch (ignore) {}
										writeResponse();
									}, writeResponse); // continue on redis errors
								} else {
									// handle persistent and non-persistent authentication
									expires = remember_me ? Date.now() + constants.AUTH_MAX_AGE : undefined;
									expiresDate = expires ? new Date(expires) : null;
									writeResponse();
								}
								return;
							}
						} catch (e) {
							console.log('Invalid JSON when attempting to parse response body for auth token');
							e.message += ' - Invalid JSON when attempting to parse response body for auth token';
							bugsense.logError(e);
						}
					}
					res.write(response_body || '');
				}
				res.end();
			});
		};

		/**
		 * perform a request
		 * @param options request options
		 * @param onSuccess function to call on successful request
		 * @param onError function to call on failure request
		 * @returns {*} return the response object
		 * @private
		 */
		var _request = function(options, onSuccess, onError, cookie){
			var request = proxy_scheme.request(extend({}, options), function(proxy_response){
				if(res.headersSent){
					return;
				}
				// update cookie on success
				if(cookie && proxy_response.statusCode === 200){
					res.cookie(cookie.name, cookie.value, cookie.prop);
				}
				onSuccess(proxy_response);
			}).on('error', function(err){
					if(typeof onError === 'function'){
						onError(err);
					}
				});
			return request;
		};<commit_msg>Concat all received buffer data. Fixes SWA-66.<commit_after>'use strict';

var express = require('express'),
	constants = require('./../config/constants'),
	config = require('./../config/config'),
	repository = require('./../util/repository'),
	bugsense = require('./../util/bugsense'),
	middleware = require('./../scripts'),
	router = express.Router(),
	http = require('http'),
	https = require('https'),
	extend = require('extend'),
	querystring = require('querystring'),
	path = '/:domain/*';

router
	.use(path, middleware.domain) // verifies that domain is valid
	.use(path, middleware.options) // creates options options to be used for proxy request
	.use(path, middleware.reverse) // reverses accept and content-type headers
	.use(path, middleware.user) // handle special case of /users/ requests
	.use(path, function(req, res){
		// Make the proxy HTTP request
		var proxy_scheme = req.options.port === 443 ? https : http;

		// make proxy request
		var _updateAccessToken = function(oldAT, newAT, obj){
			// add semantic version number:
			obj.version = constants.TOKEN_STORAGE_VERSION;

			// delete old access token, if it exists
			repository.del(oldAT);

			// set the access/refresh token in the key/value store
			repository.set(newAT, JSON.stringify(obj));
		};

		/**
		 * Will parse the response for the website by setting the headers, handling cookies etc.
		 * Notice: This method will sends data back to the website
		 * @param proxy_response The response object
		 * @private
		 */
		var _parseResponse = function(proxy_response){
			if(res.headersSent){
				return;
			}
			var chunked = proxy_response.headers['transfer-encoding'] === 'chunked';

			var response_headers = {};
			// copy accross headers from proxy response to response
			for (var header in proxy_response.headers) {
				response_headers[header] = proxy_response.headers[header];
			}

			// transform API services content-type to application/json
			if (proxy_response.headers.hasOwnProperty('content-type')) {
				if (proxy_response.headers['content-type'].indexOf(constants.BBB_CONTENT_TYPE) === 0) {
					response_headers['content-type'] = 'application/json';
				}
			}
			// set status code if chunked
			if(chunked){
				res.writeHead(proxy_response.statusCode, response_headers);
			} else {
				for(var index in response_headers){
					res.setHeader(index, response_headers[index]);
				}
				res.status(proxy_response.statusCode);
			}
			var buffers = [];
			proxy_response.on('data', function (chunk) {
				if (!chunked) {
					buffers.push(chunk);
				} else {
					res.write(chunk);
				}
			});

			proxy_response.on('end', function() {
				if (!chunked) {
					var response_body = Buffer.concat(buffers);
					// If appropriate, translate the authentication OAuth2 bearer token back to a cookie
					if ((req.options.path.indexOf(constants.AUTH_PATH_COMPONENT) !== -1 || req.options.path.indexOf(constants.AUTH_USERS_PATH) !== -1) &&
						proxy_response.headers.hasOwnProperty('content-type') &&
						proxy_response.headers['content-type'].indexOf('application/json') === 0) {
						try {
							var json_response = JSON.parse(String(response_body)),
									old_access_token,
									access_token,
									refresh_token,
									user_id_parts,
									user_id,
									body,
									remember_me,
									expires,
									expiresDate,
									writeResponse;
							if (json_response.hasOwnProperty(constants.AUTH_ACCESS_TOKEN_NAME)) {
								writeResponse = function () {
									// save new access token
									_updateAccessToken(old_access_token, access_token, {
										refresh_token: refresh_token,
										user_id: user_id,
										expires: expires
									});

									res.cookie(constants.AUTH_ACCESS_TOKEN_NAME, access_token, { path: '/api', expires: expiresDate, httpOnly: true, secure: true });

									// Strip the access and refresh tokens from the response body:
									delete json_response[constants.AUTH_REFRESH_TOKEN_NAME];
									delete json_response[constants.AUTH_ACCESS_TOKEN_NAME];

									response_body = JSON.stringify(json_response);
									res.setHeader('Content-Length', Buffer.byteLength(response_body));
									res.write(response_body);
									res.end();
								};

								// response is a refresh token request to the /oauth/token endpoint
								old_access_token = req.cookies[constants.AUTH_ACCESS_TOKEN_NAME];
								access_token = json_response[constants.AUTH_ACCESS_TOKEN_NAME];
								refresh_token = json_response[constants.AUTH_REFRESH_TOKEN_NAME];

								// get the user id from the response
								user_id_parts = json_response.user_id.split(':');
								user_id = user_id_parts[user_id_parts.length - 1];

								body = querystring.parse(req.body) || {};

								remember_me = body[constants.AUTH_PARAM_REMEMBER_ME] === 'true';

								if (!remember_me && !!old_access_token) {
									// Retrieve the expires value stored for the old access token:
									repository.get(old_access_token).then(function (value) {
										try {
											expires = JSON.parse(value).expires;
											expiresDate = expires ? new Date(expires) : null;
										} catch (ignore) {}
										writeResponse();
									}, writeResponse); // continue on redis errors
								} else {
									// handle persistent and non-persistent authentication
									expires = remember_me ? Date.now() + constants.AUTH_MAX_AGE : undefined;
									expiresDate = expires ? new Date(expires) : null;
									writeResponse();
								}
								return;
							}
						} catch (e) {
							console.log('Invalid JSON when attempting to parse response body for auth token');
							e.message += ' - Invalid JSON when attempting to parse response body for auth token';
							bugsense.logError(e);
						}
					}
					res.write(response_body);
				}
				res.end();
			});
		};

		/**
		 * perform a request
		 * @param options request options
		 * @param onSuccess function to call on successful request
		 * @param onError function to call on failure request
		 * @returns {*} return the response object
		 * @private
		 */
		var _request = function(options, onSuccess, onError, cookie){
			var request = proxy_scheme.request(extend({}, options), function(proxy_response){
				if(res.headersSent){
					return;
				}
				// update cookie on success
				if(cookie && proxy_response.statusCode === 200){
					res.cookie(cookie.name, cookie.value, cookie.prop);
				}
				onSuccess(proxy_response);
			}).on('error', function(err){
					if(typeof onError === 'function'){
						onError(err);
					}
				});
			return request;
		};
{'fraction_non_alphanumeric': 0.11927444554530904, 'fraction_numerical': 0.0019815562838198307, 'mean_word_length': 2.941724241513968, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '2811558', 'n_tokens_mistral': 5090, 'n_tokens_neox': 3726, 'n_words': 924}