Updated:

7 minute read

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