7 분 소요

REST


서버


클라이언트


예제

  • 코드
    • 서버

            import logging
            from flask import Flask, request, jsonify, redirect, url_for, make_response
            from flask_restx import Resource, Namespace, Api, fields

            index1 = Namespace(name='index1-name',
                               path='/index1',
                               description='index1 description')


            @index1.route('', methods=['GET'])
            class Index1(Resource):

                def get(self):
                    return redirect(url_for('index2-name_index2'))


            index2 = Namespace(name='index2-name',
                               path='/index2',
                               description='index2 description')


            @index2.route('', methods=['GET'])
            class Index2(Resource):

                def get(self):
                    print("\n\n")
                    print("request.method :", request.method)
                    print("request.url :", request.url)
                    print("request.url_root :", request.url_root)
                    print("request.mimetype :", request.mimetype)
                    print("request.headers :", request.headers)
                    print("request.remote_addr :", request.remote_addr)
                    if "key" in request.headers:
                        print("request.headers[key] :", request.headers["key"])

                    return jsonify({"result": "index2 ok"})


            uri = Namespace(name='uri-name', path='/uri', description='uri description')
            uri_post_put_request = uri.model(name='uri_post_put_request',
                                             model={
                                                 'key':
                                                 fields.String(description='description',
                                                               required=True,
                                                               example="value")
                                             })
            uri_get_response = uri.model(name='uri_get_response',
                                         model={
                                             'id':
                                             fields.Integer(description='description',
                                                            required=True,
                                                            example=1),
                                             'key':
                                             fields.String(description='description',
                                                           required=True,
                                                           example="value")
                                         })


            @uri.route('', methods=['GET', 'POST', 'PUT'])
            @uri.route('/<uri_id_1>', methods=['GET'])
            @uri.route('/<int:uri_id_2>', methods=['DELETE'])
            class UriGet(Resource):

                @uri.response(200, 'OK', uri_get_response)
                @uri.response(500, 'Failed')
                def get(self, uri_id_1=None):
                    print("\n\n")
                    print("request.url :", request.url)
                    print("uri_id_1 :", uri_id_1)
                    print("request.query_string :", request.query_string)
                    print("key :", request.args.get('key', ''))

                    response = {"key": "value"}
                    return jsonify(response)

                @uri.expect(uri_post_put_request)
                @uri.doc(responses={201: "Created"})
                @uri.doc(responses={500: "Internal Server Error"})
                def post(self):
                    print("\n\n")
                    print("request.method :", request.method)
                    print("request.content_type :", request.content_type)
                    print("request.content_length :", request.content_length)
                    print("request.is_json :", request.is_json)
                    if request.is_json:
                        print("request.get_json() :", request.get_json())
                    else:
                        print("request.form :", request.form)

                    response = make_response('', 201 if request.method == 'POST' else 200)
                    return response

                @uri.expect(uri_post_put_request)
                @uri.response(200, 'OK')
                def put(self):
                    self.post()

                @uri.response(204, 'No Content')
                @uri.response(404, 'Not Found')
                def delete(self, uri_id_2):
                    print("\n\n")
                    print("uri_id_2 :", uri_id_2)
                    print("request.remote_addr :", request.remote_addr)

                    response = make_response('', 204)
                    response.headers['X-TEST'] = 'value'
                    return response


            if __name__ == "__main__":
                app = Flask(__name__)

                api = Api(
                    app=app,
                    version='1.0',
                    title='title',
                    description="description",
                    contact='contact',
                    contact_email='contact_email',
                )

                api.add_namespace(index1)
                api.add_namespace(index2)
                api.add_namespace(uri)

                logging.basicConfig(level=logging.DEBUG)
                index2.logger.addHandler(logging.FileHandler("index2.log"))
                uri.logger.setLevel(logging.CRITICAL)

                print("\n")
                app.logger.debug('debug log')
                index1.logger.info('info log')
                index2.logger.warning('warning log')
                uri.logger.error('error log')
                uri.logger.critical('critical log')
                print("\n")

                app.run(debug=True, host='0.0.0.0', port=10000)
  • 클라이언트

            import requests
            import logging

            if __name__ == "__main__":
                logging.basicConfig()
                logging.getLogger().setLevel(logging.INFO)

                logging.debug('debug log')
                logging.info('info log')
                logging.warning('warning log')
                logging.error('error log')
                logging.critical('critical log')

                print("\n")
                print("----- status code ----- start")
                print("\trequests.codes.ok :", requests.codes.ok)
                print("\trequests.codes.created :", requests.codes.created)
                print("\trequests.codes.no_content :", requests.codes.no_content)
                print("\t...")
                print("----- status code ----- end\n\n")

                request = requests.options('http://127.0.0.1:10000/index1')
                print("----- options", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('allow') :", request.headers.get('allow'))
                print("----- options", request.url, "----- end\n\n")

                request = requests.options('http://127.0.0.1:10000/uri')
                print("----- options", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('allow') :", request.headers.get('allow'))
                print("----- options", request.url, "----- end\n\n")

                url = 'http://127.0.0.1:10000/index1'
                headers = {'key': 'value'}
                request = requests.get(url, headers=headers)
                print("----- get", url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers :", request.headers)
                print("\trequest.headers['Content-Type'] :",
                      request.headers['Content-Type'])
                print("\trequest.headers.get('content-type') :",
                      request.headers.get('content-type'))
                print("\trequest.text :", request.text)
                print("\trequest.encoding :", request.encoding)
                print("\trequest.content :", request.content)
                print("\trequest.json() :", request.json())
                print("\trequest.history :", request.history)
                print("----- get", request.url, "----- end\n\n")

                request = requests.head('http://127.0.0.1:10000/uri')
                print("----- head", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers :", request.headers)
                print("----- head", request.url, "----- end\n\n")

                request = requests.get('http://127.0.0.1:10000/uri', timeout=3)
                print("----- get", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers :", request.headers)
                print("\trequest.headers.get('content-type') :",
                      request.headers.get('content-type'))
                print("\trequest.json() :", request.json())
                print("----- get", request.url, "----- end\n\n")

                request = requests.get('http://127.0.0.1:10000/uri/id')
                print("----- get", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('content-type') :",
                      request.headers.get('content-type'))
                print("\trequest.json() :", request.json())
                print("----- get", request.url, "----- end\n\n")

                payload = {'key': 'value'}
                request = requests.get('http://127.0.0.1:10000/uri', params=payload)
                print("----- get", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('content-type') :",
                      request.headers.get('content-type'))
                print("\trequest.json() :", request.json())
                print("----- get", request.url, "----- end\n\n")

                payload = {'key1': 'value1', 'key2': ['value2-1', 'value2-2']}
                request = requests.get('http://127.0.0.1:10000/uri', params=payload)
                print("----- get", request.url, "----- start")
                print("\trequest.status_code :", request.status_code)
                print("----- get", request.url, "----- end\n\n")

                payload = {'key': 'value'}
                request = requests.post('http://127.0.0.1:10000/uri', data=payload)
                print("----- post", request.url, "----- 1 start")
                print("\trequest.status_code :", request.status_code)
                print("----- post", request.url, "----- 1 end\n\n")

                payload = {'key': 'value'}
                request = requests.post('http://127.0.0.1:10000/uri', json=payload)
                print("----- post", request.url, "----- 2 start")
                print("\trequest.status_code :", request.status_code)
                print("----- post", request.url, "----- 2 end\n\n")

                payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
                request = requests.put('http://127.0.0.1:10000/uri', json=payload_tuples)
                print("----- put", request.url, "----- 1 start")
                print("\trequest.status_code :", request.status_code)
                print("----- put", request.url, "----- 1 end\n\n")

                payload_dict = {'key1': ['value1', 'value2']}
                request = requests.put('http://127.0.0.1:10000/uri', json=payload_dict)
                print("----- put", request.url, "----- 2 start")
                print("\trequest.status_code :", request.status_code)
                print("----- put", request.url, "----- 2 end\n\n")

                request = requests.delete('http://127.0.0.1:10000/uri/id')
                print("----- delete", request.url, "----- 1 start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('x-test') :", request.headers.get('x-test'))
                print("\trequest.json() :", request.json())
                print("----- delete", request.url, "----- 1 end\n\n")

                request = requests.delete('http://127.0.0.1:10000/uri/123')
                print("----- delete", request.url, "----- 2 start")
                print("\trequest.status_code :", request.status_code)
                print("\trequest.headers.get('x-test') :", request.headers.get('x-test'))
                print("----- delete", request.url, "----- 2 end\n\n")
  • Swagger
    • http://127.0.0.1:10000/
  • 실행 결과
    • 서버

            $ python server.py


            [2023-04-19 11:23:25,331] DEBUG in main: debug log
            DEBUG:main:debug log
            [2023-04-19 11:23:25,331] INFO in main: info log
            INFO:flask_restx.namespace.index1-name:info log
            [2023-04-19 11:23:25,331] WARNING in main: warning log
            WARNING:flask_restx.namespace.index2-name:warning log
            [2023-04-19 11:23:25,331] CRITICAL in main: critical log
            CRITICAL:flask_restx.namespace.uri-name:critical log


             * Serving Flask app 'main'
             * Debug mode: on
            INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
             * Running on all addresses (0.0.0.0)
             * Running on http://127.0.0.1:10000
             * Running on http://192.168.14.220:10000
            INFO:werkzeug:Press CTRL+C to quit
            INFO:werkzeug: * Restarting with stat


            [2023-04-19 11:23:25,567] DEBUG in main: debug log
            DEBUG:main:debug log
            [2023-04-19 11:23:25,567] INFO in main: info log
            INFO:flask_restx.namespace.index1-name:info log
            [2023-04-19 11:23:25,567] WARNING in main: warning log
            WARNING:flask_restx.namespace.index2-name:warning log
            [2023-04-19 11:23:25,567] CRITICAL in main: critical log
            CRITICAL:flask_restx.namespace.uri-name:critical log


            WARNING:werkzeug: * Debugger is active!
            INFO:werkzeug: * Debugger PIN: 774-693-356
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "OPTIONS /index1 HTTP/1.1" 200 -
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "OPTIONS /uri HTTP/1.1" 200 -
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /index1 HTTP/1.1" 302 -



            request.method : GET
            request.url : http://127.0.0.1:10000/index2
            request.url_root : http://127.0.0.1:10000/
            request.mimetype :
            request.headers : Host: 127.0.0.1:10000
            User-Agent: python-requests/2.25.1
            Accept-Encoding: gzip, deflate
            Accept: */*
            Connection: keep-alive
            Key: value


            request.remote_addr : 127.0.0.1
            request.headers[key] : value
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /index2 HTTP/1.1" 200 -



            request.url : http://127.0.0.1:10000/uri
            uri_id_1 : None
            request.query_string : b''
            key :
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "HEAD /uri HTTP/1.1" 200 -



            request.url : http://127.0.0.1:10000/uri
            uri_id_1 : None
            request.query_string : b''
            key :
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /uri HTTP/1.1" 200 -



            request.url : http://127.0.0.1:10000/uri/id
            uri_id_1 : id
            request.query_string : b''
            key :
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /uri/id HTTP/1.1" 200 -



            request.url : http://127.0.0.1:10000/uri?key=value
            uri_id_1 : None
            request.query_string : b'key=value'
            key : value
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /uri?key=value HTTP/1.1" 200 -



            request.url : http://127.0.0.1:10000/uri?key1=value1&key2=value2-1&key2=value2-2
            uri_id_1 : None
            request.query_string : b'key1=value1&key2=value2-1&key2=value2-2'
            key :
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "GET /uri?key1=value1&key2=value2-1&key2=value2-2 HTTP/1.1" 200 -



            request.method : POST
            request.content_type : application/x-www-form-urlencoded
            request.content_length : 9
            request.is_json : False
            request.form : ImmutableMultiDict([('key', 'value')])
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "POST /uri HTTP/1.1" 201 -



            request.method : POST
            request.content_type : application/json
            request.content_length : 16
            request.is_json : True
            request.get_json() : {'key': 'value'}
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "POST /uri HTTP/1.1" 201 -



            request.method : PUT
            request.content_type : application/json
            request.content_length : 40
            request.is_json : True
            request.get_json() : [['key1', 'value1'], ['key1', 'value2']]
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "PUT /uri HTTP/1.1" 200 -



            request.method : PUT
            request.content_type : application/json
            request.content_length : 30
            request.is_json : True
            request.get_json() : {'key1': ['value1', 'value2']}
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "PUT /uri HTTP/1.1" 200 -
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "DELETE /uri/id HTTP/1.1" 405 -



            uri_id_2 : 123
            request.remote_addr : 127.0.0.1
            INFO:werkzeug:127.0.0.1 - - [19/Apr/2023 11:23:32] "DELETE /uri/123 HTTP/1.1" 204 -
  • 클라이언트

            $ python client.py


            INFO:root:info log
            WARNING:root:warning log
            ERROR:root:error log
            CRITICAL:root:critical log


            ----- status code ----- start
                    requests.codes.ok : 200
                    requests.codes.created : 201
                    requests.codes.no_content : 204
                    ...
            ----- status code ----- end


            ----- options http://127.0.0.1:10000/index1 ----- start
                    request.status_code : 200
                    request.headers.get('allow') : HEAD, OPTIONS, GET
            ----- options http://127.0.0.1:10000/index1 ----- end


            ----- options http://127.0.0.1:10000/uri ----- start
                    request.status_code : 200
                    request.headers.get('allow') : PUT, OPTIONS, GET, HEAD, POST
            ----- options http://127.0.0.1:10000/uri ----- end


            ----- get http://127.0.0.1:10000/index1 ----- start
                    request.status_code : 200
                    request.headers : {'Server': 'Werkzeug/2.2.3 Python/3.9.16', 'Date': 'Wed, 19 Apr 2023 02:23:32 GMT', 'Content-Type': 'application/json', 'Content-Length': '28', 'Connection': 'close'}
                    request.headers['Content-Type'] : application/json
                    request.headers.get('content-type') : application/json
                    request.text : {
              "result": "index2 ok"
            }

                    request.encoding : utf-8
                    request.content : b'{\n  "result": "index2 ok"\n}\n'
                    request.json() : {'result': 'index2 ok'}
                    request.history : [<Response [302]>]
            ----- get http://127.0.0.1:10000/index2 ----- end


            ----- head http://127.0.0.1:10000/uri ----- start
                    request.status_code : 200
                    request.headers : {'Server': 'Werkzeug/2.2.3 Python/3.9.16', 'Date': 'Wed, 19 Apr 2023 02:23:32 GMT', 'Content-Type': 'application/json', 'Content-Length': '21', 'Connection': 'close'}
            ----- head http://127.0.0.1:10000/uri ----- end


            ----- get http://127.0.0.1:10000/uri ----- start
                    request.status_code : 200
                    request.headers : {'Server': 'Werkzeug/2.2.3 Python/3.9.16', 'Date': 'Wed, 19 Apr 2023 02:23:32 GMT', 'Content-Type': 'application/json', 'Content-Length': '21', 'Connection': 'close'}
                    request.headers.get('content-type') : application/json
                    request.json() : {'key': 'value'}
            ----- get http://127.0.0.1:10000/uri ----- end


            ----- get http://127.0.0.1:10000/uri/id ----- start
                    request.status_code : 200
                    request.headers.get('content-type') : application/json
                    request.json() : {'key': 'value'}
            ----- get http://127.0.0.1:10000/uri/id ----- end


            ----- get http://127.0.0.1:10000/uri?key=value ----- start
                    request.status_code : 200
                    request.headers.get('content-type') : application/json
                    request.json() : {'key': 'value'}
            ----- get http://127.0.0.1:10000/uri?key=value ----- end


            ----- get http://127.0.0.1:10000/uri?key1=value1&key2=value2-1&key2=value2-2 ----- start
                    request.status_code : 200
            ----- get http://127.0.0.1:10000/uri?key1=value1&key2=value2-1&key2=value2-2 ----- end


            ----- post http://127.0.0.1:10000/uri ----- 1 start
                    request.status_code : 201
            ----- post http://127.0.0.1:10000/uri ----- 1 end


            ----- post http://127.0.0.1:10000/uri ----- 2 start
                    request.status_code : 201
            ----- post http://127.0.0.1:10000/uri ----- 2 end


            ----- put http://127.0.0.1:10000/uri ----- 1 start
                    request.status_code : 200
            ----- put http://127.0.0.1:10000/uri ----- 1 end


            ----- put http://127.0.0.1:10000/uri ----- 2 start
                    request.status_code : 200
            ----- put http://127.0.0.1:10000/uri ----- 2 end


            ----- delete http://127.0.0.1:10000/uri/id ----- 1 start
                    request.status_code : 405
                    request.headers.get('x-test') : None
                    request.json() : {'message': 'The method is not allowed for the requested URL.'}
            ----- delete http://127.0.0.1:10000/uri/id ----- 1 end


            ----- delete http://127.0.0.1:10000/uri/123 ----- 2 start
                    request.status_code : 204
                    request.headers.get('x-test') : value
            ----- delete http://127.0.0.1:10000/uri/123 ----- 2 end