function request( opts, data, clbk ) {
	var body;
	var post;
	var req;
	var res;
	var err;

	// debug( 'Query options: %s', JSON.stringify( opts ) ); // NOTE: this is NOT enabled by default, as it is possible to leak credentials in log output. Temporarily enable if you need to inspect request options, but NEVER enable this in committed code.

	if ( RE.test( opts.protocol ) ) {
		post = https.request;
	} else {
		post = http.request;
	}
	body = '';
	req = post( opts, onResponse );
	req.on( 'error', onError );
	req.write( data );
	req.end();

	/**
	* Event listener invoked after encountering an error.
	*
	* @private
	* @param {Error} error - error object
	* @returns {void}
	*/
	function onError( error ) {
		debug( 'Error encountered while querying endpoint: %s', error.message );
		if ( error instanceof Error ) {
			err = {
				'status': 500,
				'message': 'Request error: ' + error.message
			};
			return clbk( err );
		}
		return clbk( error, res, body );
	}

	/**
	* Callback invoked after receiving an HTTP response.
	*
	* @private
	* @param {Object} response - HTTP response object
	*/
	function onResponse( response ) {
		res = response;
		if ( res.statusCode !== 201 ) {
			err = {
				'status': res.statusCode,
				'message': ''
			};
		}
		debug( 'Received a response from query endpoint.' );
		debug( 'Response status: %s.', res.statusCode );

		debug( 'Response headers: %s', JSON.stringify( res.headers ) );

		res.setEncoding( 'utf8' );
		res.on( 'data', onData );
		res.on( 'end', onEnd );
	}

	/**
	* Event listener invoked upon receiving response data.
	*
	* @private
	* @param {string} chunk - data chunk
	*/
	function onData( chunk ) {
		body += chunk;
	}

	/**
	* Event listener invoked upon a response end.
	*
	* @private
	* @returns {void}
	*/
	function onEnd() {
		var data;
		if ( err ) {
			err.message = body;
			return onError( err );
		}
		// debug( 'Response body: %s', body ); // NOTE: this is NOT enabled by default as response bodies can be large, making inspection of logs difficult. Temporarily enable if you need to inspect response bodies.

		data = parse( body );
		if ( data instanceof Error ) {
			err = {
				'status': 502,
				'message': 'unable to parse endpoint response data as JSON: ' + data.message
			};
			return onError( err );
		}
		clbk( null, res, data );
	}
}
Queries an endpoint.

@private
@param {Options} opts - request options
@param {(string|Buffer)} data - request data
@param {Callback} clbk - callback to invoke upon querying an endpoint