Aller au contenu principal

Créer une API

AbyssMonitor fournit des outils pour mettre en place facilement une API avec NodeJS et TypeScript. Les outils sont conçus pour fonctionner avec Express.

Setup

Créer votre premier Middleware

import { Request, Response, NextFunction } from 'express';
import * as contentType from 'content-type';
import { IMonitorLocals, Logger, Middleware } from '@abyss-project/monitor';

export const ALLOWED_REQUEST_TYPES = [
'application/json',
'multipart/form-data',
'application/x-www-form-urlencoded',
];

@Middleware()
export default class MyMiddleware {
private static readonly logger = new Logger({});

public async run(
req: Request,
res: Response<unknown, IMonitorLocals>,
next: NextFunction,
): Promise<void> {
if (req.headers['content-type']) {
const contentT = contentType.parse({ headers: req.headers });

if (!ALLOWED_REQUEST_TYPES.includes(contentT.type)) {
// Throw an error because invalid request type
}
}

next();
}
}

Créer votre premier Controller

import { Request, Response } from 'express';
import { Controller, Get, IMonitorLocals, Logger, Middlewares } from '@abyss-project/monitor';
import MyMiddleware from './../middlewares/my-middleware.middleware.ts'
@Controller({ prefixPath: '/' })
@Middlewares([MyMiddleware])
export default class MyController {
private static readonly logger = new Logger({});

@Get({
path: '/hello-world',
})
@Middlewares([])
async helloWorld(
req: Request<Record<string, never>, string, void>,
res: Response<string, IMonitorLocals>,
): Promise<void> {
res.send(`Hello world !`);
}
}

Créer l'application Express

import {
IMonitorLocals,
contextMiddleware,
controllerLoader,
loggerEndpointMiddleware,
loggerSetupMiddleware,
Logger,
} from '@abyss-project/monitor';
import express, { Response, Request, NextFunction, Router } from 'express';
import { json, urlencoded } from 'body-parser';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import helmet from 'helmet';
import compression from 'compression';
import swaggerUi from 'swagger-ui-express';
import MyController from './controllers/my-controller.controller.ts';
import MyMiddleware from './middlewares/my-middleware.middleware.ts';
require('express-async-errors');

const PREFIX = '/api';
const PORT = 5000;

const apiLogger = new Logger({
shouldDisableRemoteLogging: process.env.NODE_ENV === 'DEVELOPMENT',
});

const init = async (): Promise<express.Application> => {
const app = express();
// Adding the ContextMiddleware
app.use(contextMiddleware);

// Disabling the PoweredBy Express header
app.disable('x-powered-by');

// Enabling CORS and set kind of request my API will accept because
// I want to make this API public
app.use(cors());
app.use((req: Request, res: Response<unknown, ILocals>, next: NextFunction) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization',
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
res.setHeader('Access-Control-Expose-Headers', 'Content-disposition, filename');
next();
});

app.use(urlencoded({ extended: true }));
app.use(json());
app.use(cookieParser());
app.use(helmet());
app.use(compression());

// Setting logger middleware
app.use(loggerSetupMiddleware);
app.use((req, res: Response<unknown, IMonitorLocals>, next) =>
loggerEndpointMiddleware(apiLogger, req, res, next),
);

// Setting up the swagger
const {
swagger: { tags, paths },
} = await controllerLoader(app, {
prefix: PREFIX,
router: Router,
middlewares: [MyMiddleware],
controllers: [MyController],
});

app.use(
(error: Error, _req: Request, _res: Response<unknown, IMonitorLocals>, _next: NextFunction) => {
// Do what you want with the error
apiLogger.error(error);
},
);

app
.listen(PORT, () => {
apiLogger.info(`API started on port ${PORT}`);
})
.on('error', (error) => {
apiLogger.error(`API failed to start. Error: ${error}`);
});

const defaultSwagger = {
openapi: '3.0.3',
info: {
title: 'My First API',
description: '',
version: '1.0',
termsOfService: 'http://swagger.io/terms/',
contact: {
},
license: {
name: 'Apache 2.0',
},
url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
},
produces: ['application/json'],
host: `http://localhost:${PORT}`,
basePath: PREFIX,
tags,
paths,
};

app.use(
'/swagger',
(req: Request, res: Response<unknown, IMonitorLocals>, next: NextFunction) => {
// Disabling the log on swagger endpoint to not spam with useless logs
res.locals.shouldNotPublishLog = true;
next();
},
swaggerUi.serve,
// eslint-disable-next-line @typescript-eslint/no-var-requires
swaggerUi.setup(defaultSwagger),
);

return app;
};

await init();