User Tools

Site Tools


en:python:webapi

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:python:webapi [2021/04/14 23:29] lonclegren:python:webapi [2021/04/25 22:58] (current) – [Architecture] lonclegr
Line 12: Line 12:
 Before going further: yes I know that a lot of solutions may solve this issue but the target is to make the POC in less than one hour. As I used to develop Web Restful API then it is my choice. Before going further: yes I know that a lot of solutions may solve this issue but the target is to make the POC in less than one hour. As I used to develop Web Restful API then it is my choice.
  
 +===== Architecture =====
  
 +{{ :en:python:web-api.png?600 |Architecture WebAPI}}
 +
 +{{ :en:python:web-api.dia |Source DIA}}
 ===== Client side ===== ===== Client side =====
  
Line 18: Line 22:
  
 <file powershell client_side.ps1 > <file powershell client_side.ps1 >
 +# init
 $who=whoami $who=whoami
 $computer=hostname $computer=hostname
 $server="my-server.domain.com" $server="my-server.domain.com"
  
-Invoke-WebRequest ("http://{2}:5000/my_action/start/{0}/{1}" -f ($who -replace "\\", "@"), $computer, $server) -Method POST+# before the main command, let's call the API 
 +Invoke-WebRequest ("http://{2}:5000/my_command/start/{0}/{1}" -f ($who -replace "\\", "@"), $computer, $server) -Method POST 
 + 
 +# main command 
 +my_action 
 + 
 +# after the main command, let's call the API 
 +Invoke-WebRequest ("http://{2}:5000/my_command/end/{0}/{1}" -f ($who -replace "\\", "@"), $computer, $server) -Method POST 
 </file> </file>
  
Line 30: Line 43:
 StatusCode        : 201 StatusCode        : 201
 StatusDescription : Created StatusDescription : Created
-Content           : {"user": "my_user", "action": "my_action", "ip_remote": "0.1.2.3", "computer":+Content           : {"user": "my_user", "action": "start", "ip_remote": "0.1.2.3", "computer":
                     "my_computer"}                     "my_computer"}
  
Line 40: Line 53:
                     Server: gunicorn/20.0.4                     Server: gunicorn/20.0.4
  
-                    {"user": "my_user", "action": "my_acti...+                    {"user": "my_user", "action": "star...
 Forms             : {} Forms             : {}
 Headers           : {[Connection, close], [Content-Length, 115], [Content-Type, application/json], [Date, Tue, 26 May 2020 13:46:28 Headers           : {[Connection, close], [Content-Length, 115], [Content-Type, application/json], [Date, Tue, 26 May 2020 13:46:28
Line 50: Line 63:
 RawContentLength  : 115 RawContentLength  : 115
 </code> </code>
 +
 +If you are running linux laptop you can adapt the script with curl.
 +
 +<code bash>
 +curl -i -XPOST --silent http://localhost:5000/my_command/start/toto/computer
 +HTTP/1.1 201 CREATED
 +Server: gunicorn
 +Date: Fri, 16 Apr 2021 03:07:27 GMT
 +Connection: close
 +Content-Type: application/json
 +Content-Length: 86
 +
 +{"user": "toto", "action": "start", "ip_remote": "127.0.0.1", "computer": "computer"}
 +</code>
 +===== Server side =====
 +
 +==== Run it ====
 +
 +
 +<code bash>
 +python3 -m venv venv
 +source venv/bin/activate
 +pip install -r requirements.txt
 +gunicorn  --bind 0.0.0.0:5000 wsgi:app
 +</code>
 +==== Logger ====
 +
 +<file python logger.py>
 +import logging
 +
 +logger = logging.getLogger('api')
 +logger.setLevel(logging.DEBUG)
 +# create file handler which logs even debug messages
 +fh = logging.FileHandler('api.log')
 +fh.setLevel(logging.INFO)
 +# create console handler with a higher log level
 +ch = logging.StreamHandler()
 +ch.setLevel(logging.DEBUG)
 +# create formatter and add it to the handlers
 +formatter = logging.Formatter(
 +    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
 +)
 +ch.setFormatter(formatter)
 +fh.setFormatter(formatter)
 +# add the handlers to logger
 +logger.addHandler(ch)
 +logger.addHandler(fh)
 +</file>
 +
 +==== WSGI ====
 +
 +<file python wsgi.py>
 +from api import app
 +
 +if __name__ == "__main__":
 +    app.run()
 +</file>
 +==== API ====
 +
 +<file python api.py>
 +from flask import Flask, request
 +from flask_restful import Resource, Api
 +from logger import logger
 +
 +
 +app = Flask(__name__)
 +api = Api(app)
 +
 +
 +class HelloWorld(Resource):
 +    def post(self, user, action, computer):
 +        logger.info(f"{computer},{action},{user},{request.remote_addr}")
 +        return {
 +            "user": user,
 +            "action": action,
 +            "ip_remote": request.remote_addr,
 +            "computer": computer
 +        }
 +
 +
 +api.add_resource(
 +    HelloWorld,
 +    '/my_command/<string:action>/<string:user>/<string:computer>'
 +)
 +
 +if __name__ == '__main__':
 +    app.run(debug=True, host="0.0.0.0")
 +</file>
 +
 +==== Requirements ====
 +
 +<file text requirements.txt>
 +flake8
 +flask_restful
 +gunicorn
 +</file>
en/python/webapi.1618457363.txt.gz · Last modified: 2021/04/14 23:29 by lonclegr