Swagger란?
- Open Api Specification을 위한 프레임워크
- API들이 가지고 있는 스펙을 명세, 관리할 수 있는 프로젝트
- API 문서화를 수작업으로 하는 것은 매우 귀찮고, API가 수정될때마다 문서를 같이 수정하는 것은 더더욱 귀찮다. 이러한 불편함을 줄여주기 위해 개발된 프로젝트
Flask-RESTx / Flask-RESTPlus
- REST API를 빠르게 빌드하고, Swagger 포함 여러 기능들이 들어있는 Flask 확장 프레임워크이므로 Flask에 익숙하다면 쉽게 접근할 수 있다.
- flask-restplus 프로젝트 중단?
- flask-restx로 fork되었다
- 여기에서는 기초적인 Flask 예제에서 하는 것처럼 function을 route시킬 수 없고, Resource에서 파생된 클래스만 이용할 수 있다. 따라서 기존 function은 class로 변경해야 한다.
코드에 적용하기
- Resource를 상속한 클래스에 get, post, put 등 rest api method에 해당하는 function들을 만들면 swagger UI에 추가되고, route 함수 안에 method 인자를 넣지 않아도 해당하는 method의 요청을 연결해준다.
@resource1_api.route('/resource1')
class FirstResource(Resource):
@resource1_api.expect(parser)
def test_func(self):
result = {'result_msg': 'Success'}
return result, 200
...(후략)
@resource2_api.route('/resource2')
class SecondResource(Resource):
@resource2_api.expect(parser)
def get(self):
result = {'result_msg': 'Success'}
return result, 200
...(후략)
- flask의 Blueprint와 같이 연관된 리소스들을 묶어 api를 계층적으로 관리하고 싶은 경우 Namespace를 사용한다.
resource1_app = Blueprint('resource1_app', __name__, url_prefix='/routes')
resource1_api = Namespace('resource1_api', path='/routes')
@resource1_api.route('/resource1')
class FirstResource(Resource):
@resource1_api.expect(parser)
def get(self):
result = {'result_msg': 'Success'}
return result, 200
...(후략)
app = Flask(__name__,
static_url_path='',
static_folder='static',
template_folder='templates'
)
app.register_blueprint(resource1_app)
api = Api(app, title='My API', doc='/doc')
api.add_namespace(resource1_api))
- @resource1_api.expect(parser) 를 이용해 api 문서에 필요한 파라미터들을 추가할 수 있다. 이 때 parser는 flask-restx의 reqparse를 사용하면 되고, python argparse와 사용법이 유사하다.
from flask-restx import Namespace, Resource, reqparse, Api
parser = reqparse.RequestParser()
parser.add_argument('page', type=int, default=1, help='페이지 번호')
parser.add_argument('page_count', type=int, default=50, help='페이지 당 item 수')
@resource1_api.route('/resource1')
class FirstResource(Resource):
@resource1_api.expect(parser)
def get(self):
result = {'result_msg': 'Success'}
return result, 200
...(후략)
- @resource1_api.response() 를 이용해 documentation에 response에 대한 설명을 추가할 수 있다. 상태값은 result dict와 함께 반환하면 된다.
@resource1_api.route('/resource1')
class FirstResource(Resource):
@resource1_api.expect(parser)
@resource1_api.response(200, 'Success')
@resource1_api.response(400, 'Bad Request')
def get(self):
try:
(중략)
result = {
'result_msg' : '성공',
'result_count' : len(result_list),
'result_list' : result_list
}, 200
except Exception as e :
LOG.error(e)
result = {
'result_msg' : f'오류발생 ::: {e}'
}, 400
return result
참고