bindings/http/emitter_binary.js

const axios = require("axios");
const EmitterV1 = require("./v1").BinaryEmitter;
const EmitterV3 = require("./v03").BinaryEmitter;

const {
  HEADERS,
  BINARY_HEADERS_03,
  BINARY_HEADERS_1,
  HEADER_CONTENT_TYPE,
  DEFAULT_CONTENT_TYPE,
  DATA_ATTRIBUTE,
  SPEC_V1,
  SPEC_V03
} = require("./constants.js");

const defaults = {
  [HEADERS]: {
    [HEADER_CONTENT_TYPE]: DEFAULT_CONTENT_TYPE
  },
  method: "POST"
};

/**
 * A class to emit binary CloudEvents over HTTP.
 */
class BinaryHTTPEmitter {
  /**
   * Create a new {BinaryHTTPEmitter} for the provided CloudEvent specification version.
   * Once an instance is created for a given spec version, it may only be used to send
   * events for that version.
   * Default version is 1.0
   * @param {string} version - the CloudEvent HTTP specification version.
   * Default: 1.0
   */
  constructor(version) {
    if (version === SPEC_V1) {
      this.headerByGetter = EmitterV1;
      this.extensionPrefix = BINARY_HEADERS_1.EXTENSIONS_PREFIX;
    } else if (version === SPEC_V03) {
      this.headerByGetter = EmitterV3;
      this.extensionPrefix = BINARY_HEADERS_03.EXTENSIONS_PREFIX;
    }
  }

  /**
   * Sends this cloud event to a receiver over HTTP.
   *
   * @param {Object} options The configuration options for this event. Options
   * provided other than `url` will be passed along to Node.js `http.request`.
   * https://nodejs.org/api/http.html#http_http_request_options_callback
   * @param {URL} options.url The HTTP/S url that should receive this event
   * @param {Object} cloudevent the CloudEvent to be sent
   * @returns {Promise} Promise with an eventual response from the receiver
   */
  async emit(options, cloudevent) {
    const config = { ...options, ...defaults };
    const headers = config[HEADERS];

    Object.keys(this.headerByGetter)
      .filter((getter) => cloudevent[getter]())
      .forEach((getter) => {
        const header = this.headerByGetter[getter];
        headers[header.name] = header.parser(cloudevent[getter]());
      });

    // Set the cloudevent payload
    const formatted = cloudevent.format();
    let data = formatted.data;
    data = (formatted.data_base64 ? formatted.data_base64 : data);

    // Have extensions?
    const exts = cloudevent.getExtensions();
    Object.keys(exts)
      .filter((ext) => Object.hasOwnProperty.call(exts, ext))
      .forEach((ext) => {
        headers[this.extensionPrefix + ext] = exts[ext];
      });

    config[DATA_ATTRIBUTE] = data;
    config.headers = headers;

    // Return the Promise
    return axios.request(config);
  }
}

module.exports = BinaryHTTPEmitter;