DEV Community

Luigi Zaccagnini
Luigi Zaccagnini

Posted on

Planning for Contributing to Telescope

Hello! Welcome to another blog post about contributing to open source. This blog post I am going to discuss the issue I picked to solve and how I am planning to solve it.

Issue at Hand

The issue I decided to choose for this was issue 2444. This issue is about adding CORS to the health checks in Telescope. CORS(cross-origin resource sharing) allows for restricted resources (Stylesheets, scripts, etc.) from one domain to be accessed from another domain. For this issue, when Satellite another Seneca open source project tries to communicate with telescope it causing the CORS issue.

Action Plan

Since this issue requires me to add CORS to satellites health checks, I will have to implement CORS into the src/satellite.js. Here is a rough idea:

const { createTerminus } = require('@godaddy/terminus');

const { createApp, createRouter } = require('./app');
const redis = require('./redis');
const elastic = require('./elastic');
const logger = require('./logger');
const cors = require('cors');

function createServer(app, credentials) {
  // If we're given key/cert credentials, use HTTPS,otherwiseHTTP 

  app.use(cors()); 

  if (credentials) {
    return require('https').createServer(credentials, app);
  }
  return require('http').createServer(app);
}

class Satellite {
  constructor(options = {}) {
    // If we're given a healthCheck function, we'll use it with terminus below.
    // NOTE: this function should return a Promise.
    this.healthCheck =
      typeof options.healthCheck === 'function' ? options.healthCheck : () => Promise.resolve();

    // If we're given a shutDown function, we'll use it with terminus below.
    // NOTE: this function should return a Promise.
    this.shutDown =
      typeof options.shutDown === 'function' ? options.shutDown : () => Promise.resolve();

    // Keep track of credentials if we're passed any
    this.credentials = options.credentials;
    // Use the router passed to us
    this.router = options.router || createRouter();
    // Expose the app
    this.app = createApp(this.router, options);
  }

  start(port, callback) {
    if (this.server) {
      throw new Error('server already started');
    }

    if (typeof port !== 'number') {
      throw new Error(`port number required, got ${port}`);
    }

    // Expose the server
    this.server = createServer(this.app, this.credentials);

    // Graceful shutdown and healthcheck
    createTerminus(this.server, {
      healthChecks: {
        '/healthcheck': this.healthCheck,
      },
      signal: 'SIGINT',
      onSignal() {
        // Do any async cleanup required to gracefully shutdown. The calls to
        // redis/elastic shutDown() will be no-ops if no connections are open.
        return Promise.all([this.shutDown(), redis.shutDown(), elastic.shutDown()]).catch((err) =>
          logger.error({ err }, 'unexpected error while shutting down')
        );
      },
      logger: (...args) => logger.error(...args),
    });

    // Start the server
    this.server.listen(port, callback);
  }

  stop(callback) {
    const self = this;

    function finished() {
      self.server = null;
      if (typeof callback === 'function') {
        callback();
      }
    }

    if (!this.server) {
      finished();
      return;
    }

    this.server.close(finished);
  }
}

module.exports = Satellite;
Enter fullscreen mode Exit fullscreen mode

Another solution could be to use set headers:

res.writeHead(200, 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET');
Enter fullscreen mode Exit fullscreen mode

This is a plan I hope works but I have much to find out when I start working on the project. Stay tuned for my more in depth blog about working on the issue.

Discussion (0)