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 =====
  
 From client side, we are going to use Powershell command as it is native to Windows 10. From client side, we are going to use Powershell command as it is native to Windows 10.
  
-<file client_side.ps1 powershell>+<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.1618457345.txt.gz · Last modified: 2021/04/14 23:29 by lonclegr