Upload a CloudFormation response for a Custom Resource

@param {object} event the Lambda event payload received by the handler function
@param {object} context the Lambda context received by the handler function
@param {string} responseStatus the response status, either 'SUCCESS' or 'FAILED'
@param {string} physicalResourceId CloudFormation physical resource ID
@param {object} [responseData] arbitrary response data object
@param {string} [reason] reason for failure, if any, to convey to the user
@returns {Promise} Promise that is resolved on success, or rejected on connection error or HTTP error response
function (event, context, responseStatus, physicalResourceId, responseData, reason) {
  return new Promise((resolve, reject) => {
    const https = require('https');
    const { URL } = require('url');

    var responseBody = JSON.stringify({
      Status: responseStatus,
      Reason: reason,
      PhysicalResourceId: physicalResourceId || context.logStreamName,
      StackId: event.StackId,
      RequestId: event.RequestId,
      LogicalResourceId: event.LogicalResourceId,
      Data: responseData
    });

    const parsedUrl = new URL(event.ResponseURL || defaultResponseURL);
    const options = {
      hostname: parsedUrl.hostname,
      port: 443,
      path: parsedUrl.pathname + parsedUrl.search,
      method: 'PUT',
      headers: {
        'Content-Type': '',
        'Content-Length': responseBody.length
      }
    };

    https.request(options)
      .on('error', reject)
      .on('response', res => {
        res.resume();
        if (res.statusCode >= 400) {
          reject(new Error(`Server returned error ${res.statusCode}: ${res.statusMessage}`));
        } else {
          resolve();
        }
      })
      .end(responseBody, 'utf8');
  });
}