Skip to content

Latest commit

 

History

History
81 lines (71 loc) · 2.47 KB

async-example.md

File metadata and controls

81 lines (71 loc) · 2.47 KB

Async Example

This includes three parts:

  • the caller, which is a middleware for the OpenAPI Factory library
  • an async wrapper, which is a custom class to contain helpers for validation.
  • a pre-step is to call compileValidator during the build step and save the compiledSpecValidation.json, so that it will run faster on production execution.
// OpenAPI Factory wrapper
let api = new Api({
  async requestMiddleware(request, context) {
    modelValidator.startValidation(request);
    if (request.httpMethod !== 'GET') {
      await modelValidator.ensureValidation();
    }
    return request;
  },
  async responseMiddleware(request, response) {
    try {
      await modelValidator.ensureValidation();
    } catch (error) {
      throw error;
    }
    return response;
  },
  errorMiddleware(request, error) {
    if (error.code === 'InvalidInputRequest') {
      return { statusCode: 400, body: { errorCode: 'InvalidRequest', title: error.message.title } }
    }

    return { statusCode: 500, body: { title: 'Unexpected error' } };
  }
});
class ModelValidator {
  constructor() {
    this.validator = null;
    this.validationAsync = null;
  }

  getOpenApiValidationProvider(spec) {
    const path = require('path');
    const { OpenApiValidator } = require('openapi-data-validator');
    const compiledFilePath = path.join(__dirname, 'compiledSpecValidation.json');
    return new OpenApiValidator({ apiSpec: spec, compiledFilePath: compiledFilePath });
  }

  async compileValidator() {
    const spec = import('./openapi.js').then(doc => doc.default);
    const openApiValidator = this.getOpenApiValidationProvider(spec);
    await openApiValidator.compileValidator();
  }

  getValidator() {
    if (this.validator) {
      return this.validator;
    }

    const openApiValidator = this.getOpenApiValidationProvider();
    return this.validator = openApiValidator.loadValidator();
  }

  startValidation(request) {
    this.validationAsync = this.getValidator().then(validator => validator(request));
    // Ensure validation may never be called, and in those cases, we want to avoid an uncaught exception
    this.validationAsync.catch(() => {});
  }

  async ensureValidation() {
    try {
      await this.validationAsync;
    } catch (error) {
      require('error-object-polyfill');
      throw Error.create({ title: `InvalidRequest: ${error.message}.` }, 'InvalidInputRequest);
    }
  }
}

module.exports = new ModelValidator();