Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate request and response #44

Closed
8 tasks done
skgndi12 opened this issue Jul 3, 2023 · 4 comments · Fixed by #81
Closed
8 tasks done

Validate request and response #44

skgndi12 opened this issue Jul 3, 2023 · 4 comments · Fixed by #81
Assignees
Labels
api enhancement New feature or request

Comments

@skgndi12
Copy link
Collaborator

skgndi12 commented Jul 3, 2023

  • Research
    • How to Validate a Request
    • Related Packages
  • Add request validation middleware
    • Convert error type
    • Validate default error response
  • Update related dependency
    • Tspec
@skgndi12 skgndi12 added enhancement New feature or request api labels Jul 3, 2023
@skgndi12 skgndi12 self-assigned this Jul 3, 2023
@skgndi12 skgndi12 added this to Alpha Jul 3, 2023
@skgndi12
Copy link
Collaborator Author

skgndi12 commented Jul 3, 2023

@skgndi12 skgndi12 moved this to Todo in Alpha Jul 3, 2023
@skgndi12 skgndi12 moved this from Todo to In Progress in Alpha Jul 12, 2023
@skgndi12
Copy link
Collaborator Author

Request validate package 조사

Package 수치 비교표

Package Stars Open issues Closed issues Last commit
class-validator 9.6k 204 711 2023.07.14
express-validator 5.6k 46 813 2023.07.15
express-openapi-validator 781 131 250 2023.05.01

Package 간 기능 비교

class-validator

특징

  • Class 에 decorator 를 적용하여 각 propertry 들을 validate 하는 패키지

장점

  1. 각 필드에 대해 정밀한 validation 내용들을 작성할 수 있다. (자세한 내용)

단점

  1. 기능 구현이 class 를 베이스로 이루어져 있기 때문에 plain object 에 적용하기 위해서는 별도의 class instantiate 하는 과정을 거쳐야 한다.
  2. 각 필드마다 검증할 내용들을 데코레이터로 작성해야하기 때문에 작성해야될 코드가 많다.
  3. 1의 내용대로 class instantiate 하는 과정이 필수이기에 target class 를 알아야 검증할 수 있다. 따라서 요청의 타입 정보를 알고있는 handler 수 만큼의 validate 함수 호출 코드 중복이 발생할 수 있다.

예시 코드

import {
  validate,
  validateOrReject,
  Contains,
  IsInt,
  Length,
  IsEmail,
  IsFQDN,
  IsDate,
  Min,
  Max,
} from 'class-validator';

export class Post {
  @Length(10, 20)
  title: string;

  @Contains('hello')
  text: string;

  @IsInt()
  @Min(0)
  @Max(10)
  rating: number;

  @IsEmail()
  email: string;

  @IsFQDN()
  site: string;

  @IsDate()
  createDate: Date;
}

let post = new Post();
post.title = 'Hello'; // should not pass
post.text = 'this is a great post about hell world'; // should not pass
post.rating = 11; // should not pass
post.email = 'google.com'; // should not pass
post.site = 'googlecom'; // should not pass

validate(post).then(errors => {
  // errors is an array of validation errors
  if (errors.length > 0) {
    console.log('validation failed. errors: ', errors);
  } else {
    console.log('validation succeed');
  }
});

validateOrReject(post).catch(errors => {
  console.log('Promise rejected (validation failed). Errors: ', errors);
});
// or
async function validateOrRejectExample(input) {
  try {
    await validateOrReject(input);
  } catch (errors) {
    console.log('Caught promise rejection (validation failed). Errors: ', errors);
  }
}

express-validator

특징

  • 미리 정의된 express 의 middleware 들을 사용하여 request 를 validate 및 sanitize 하는 패키지

장점

  1. Validation chain 을 활용하여 검증과 내용의 정제를 원하는 순서대로 구성할 수 있다.

단점

  1. Validation chain 을 재사용할때 버그가 발생할 수 있다.(참고 )
  2. 1의 버그를 막기 위해서는 매번 같은 검증 코드를 작성해야 한다.

예시 코드

import * as express from 'express';
import { query, validationResult } from 'express-validator';
const app = express();

app.use(express.json());
app.get('/hello', query('person').notEmpty(), (req, res) => {
  const result = validationResult(req);
  if (result.isEmpty()) {
    return res.send(`Hello, ${req.query.person}!`);
  }

  res.send({ errors: result.array() });
});

app.listen(3000);

express-openapi-validator

특징

  • OAS(OpenAPI Specification) 에 명시된 내용을 통해서 request 및 response 를 validation 하는 패키지

장점

  1. OAS 의 schema 내용을 보고 validate 하고 대부분의 타입들은 기본적으로 지원하기 때문에 작성해야될 코드의 양이 적음.(미리 정의된 middleware 를 적용하기만 하면 됨)
  2. 풍부한 에러 내용 제공 (status code 포함)

단점

  1. 패키지의 에러 형태를 서버에서 이해할 수 있게 가공하는 작업이 필요함.
  2. 문서 내용에서 부족한 내용이 일부 보임.

예시 코드

const express = require('express');
const path = require('path');
const http = require('http');
const app = express();

// 1. Import the express-openapi-validator library
const OpenApiValidator = require('express-openapi-validator');

// 2. Set up body parsers for the request body types you expect
//    Must be specified prior to endpoints in 5.
app.use(express.json());
app.use(express.text());
app.use(express.urlencoded({ extended: false }));

// 3. (optionally) Serve the OpenAPI spec
const spec = path.join(__dirname, 'api.yaml');
app.use('/spec', express.static(spec));

// 4. Install the OpenApiValidator onto your express app
app.use(
  OpenApiValidator.middleware({
    apiSpec: './api.yaml',
    validateResponses: true, // <-- to validate responses
  }),
);

// 5. Define routes using Express
app.get('/v1/pets', function (req, res, next) {
  res.json([
    { id: 1, type: 'cat', name: 'max' },
    { id: 2, type: 'cat', name: 'mini' },
  ]);
});

// 6. Create an Express error handler
app.use((err, req, res, next) => {
  // 7. Customize errors
  console.error(err); // dump error to console for debug
  res.status(err.status || 500).json({
    message: err.message,
    errors: err.errors,
  });
});

http.createServer(app).listen(3000);

결론

신뢰성의 측면에서 star 수 , open / close issue 의 비율등의 수치는 class-validatorexpress-validator 가 좋은 면이 있음. 하지만, 매번 같은 내용의 코드를 작성해야 하고 패키지의 기능 구현 방식으로 인한 고정적인 구조(i.e validate 를 위해서는 class instance 하는 과정이 포함되어야 한다든지)는 사용성에 큰 제약이 있음.
따라서, 패키지의 신뢰성은 떨어지더라도 사용하기에는 보다 더 깔끔한 구조를 가지고 있는 express-openapi-validator 를 사용하기로 결정.
다만, 신뢰성이 떨어지는 패키지이기 때문에 충분한 테스트 및 repo 에 올라온 이슈 내용들을 확인할 필요가 있음.

@skgndi12
Copy link
Collaborator Author

@isutare412 @2wheeh 웹 훅에서 에러가 지속적으로 발생해서 문서 공유를 위해 태그합니다.
스크린샷 2023-07-20 오후 8 40 25

skgndi12 added a commit that referenced this issue Aug 11, 2023
…t-and-response

[#44] Validate request and response
@skgndi12 skgndi12 moved this from In Progress to Todo in Alpha Sep 26, 2023
@skgndi12 skgndi12 moved this from Todo to In Progress in Alpha Nov 30, 2023
@skgndi12
Copy link
Collaborator Author

skgndi12 added a commit that referenced this issue Dec 3, 2023
…t-response

[#44] Update package for generating OpenAPI Spec
@github-project-automation github-project-automation bot moved this from In Progress to Done in Alpha Dec 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api enhancement New feature or request
Projects
Status: Done
1 participant