Flask-RESTX로 Rest API 서버 구성 & Swagger 문서 작성 - 2

지난 포스트에서 데이터베이스와 Flask를 연동한 것에 이어서 API 설계와 구현을 하려고 한다.

 

Flask-RESTX로 Rest API 서버 구성 & Swagger 문서 작성 - 1

깃헙 레포: https://github.com/Comparelt/comparelt-api GitHub - Comparelt/comparelt-api: The backend server with Flask & PostgreSQL The backend server with Flask & PostgreSQL. Contribute to Comparelt..

eight20.tistory.com

필요한 API의 기능적인 구분은 다음과 같다

  • 로그인/회원가입 API
  • 크롤링 API
  • 제품 검색 API

로그인/ 회원 가입 API는 flask-restx와 JWT를 사용하여 회원가입과 로그인 유저를 관리하는 것으로 하였다.

Flask 서버의 메인인 app.py에 아래와 같은 내용을 추가하여 API 서버 프레임을 만드는 동시에 Swagger 설명을 작성한다.

# app.py
				--------- 생략 ---------
# API 서버 프레임을 구성하고, title과 version을 통해 swagger에 작성합니다.
api = Api(app, version='0.1', title="Comparelt's API Server") 

api.add_namespace(Auth, '/auth') # Auth API를 API 서버에 추가합니다.

위와 같이 넣고 Flask 서버를 시작하고, 터미널에 출력되어 있는 ip로 접속해보면 다음과 같이 Swagger로 API 문서가 정리되어 있는 것을 볼 수 있다.

Auth API를 다음과 같이 작성하였다.

#api/auth/__init__.py

Auth = Namespace(name="Auth", description="Auth API")

users = {}  # 데이터베이스에서 유저 정보를 가져오는 로직 추가후 변경

user_fields = Auth.model('Email', {
    'email': fields.String(description='A User Email', required=True, example="dku@example.com")
}) # Swaager에 설명, 예시 및 require을 입력한다.

user_fields_auth = Auth.inherit('User Auth', user_fields, {
    'password': fields.String(description='Password', required=True, example="password"),
    'username': fields.String(description='Username', required=True, example='dku')
})


@Auth.route('/signup')
class AuthRegister(Resource):
    @Auth.expect(user_fields_auth)
    @Auth.doc(responses={200: 'Success'})
    @Auth.doc(responses={409: 'Duplicated user'})
    def post(self):
        email = request.json['email']
        password = request.json['password']
        if email in users:
            return {
                       "message": "Duplicated user"
                   }, 409
        else:
            users[email] = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())  # save password
            return {
                       'Authorization': jwt.encode({'email': email}, "secret", algorithm="HS256").decode("UTF-8")
                   }, 200


@Auth.route('/login')
class AuthLogin(Resource):
    @Auth.expect(user_fields_auth)
    @Auth.doc(responses={200: 'Success'})
    @Auth.doc(responses={401: 'UnAuthorized'})
    @Auth.doc(responses={404: 'User Not Found'})
    def post(self):
        email = request.json['email']
        password = request.json['password']
        if email not in users:
            return {
                       "message": "User Not Found"
                   }, 404
        elif not bcrypt.checkpw(password.encode('utf-8'), users[email]):  # If password is correct
            return {
                       "message": "Auth Failed"
                   }, 401
        else:
            return {
                       'Authorization': jwt.encode({'email': email}, "secret", algorithm="HS256").decode("UTF-8")
                       # return as String
                   }, 200


@Auth.route('/get')
class AuthGet(Resource):
    @Auth.header(name='JWT',
                 description='Authorization which you must included in header', example="eyJ0eo02e5tg")
    @Auth.doc(responses={200: 'Success'})
    @Auth.doc(responses={401: 'Login Failed'})
    def get(self):
        header = request.headers.get('Authorization')  # Authorization into request header
        if header is None:
            return {"message": "Please Login"}, 401
        data = jwt.decode(header, "secret", algorithm="HS256")
        return data, 200

위와 같이 구성하고 Flask를 재시작하고, Swaager를 보면 아래와 같이 API가 추가되고, 해당 설명, 예시, 필수 사항이 입력되어있다.

이번 포스트는 로그인 / 회원가입 API를 추가하고, API 관련 설명을 Swagger로 정리하였다.