===================== Web Server with Flask ===================== Basic Flask Server to serve static html files ============================================= My use case is simple: Using my documention built with Sphinx as a content for my Web server. Creating a basic Flask Application ---------------------------------- This Application has one function that uses the User input to display some custom text. .. code-block:: python from flask import Flask app = Flask(__name__) @app.route('/user/') def user(name): return '

Hello, {}!

'.format(name) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=80) .. note:: To access it from any device on your local network, set host='0.0.0.0' Serving Static files -------------------- The method send_static_files is used to output the build of our sphinx project. .. code-block:: python from flask import Flask app = Flask(__name__, static_url_path='/', static_folder='_build/') @app.route('/') @app.route('/') def serve_sphinx_docs(path='index.html'): return app.send_static_file(path) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=80) Run a production server ======================= When running publicly rather than in development, you should not use the built-in development server (flask run). The development server is provided by Werkzeug for convenience, but is not designed to be particularly efficient, stable, or secure. Instead, use a production WSGI server. For example, to use Waitress, first install it in the virtual environment: .. code-block:: bash $ pip install waitress Creat another script to import waitress and your Flask App and use the serve method: .. code-block:: python from waitress import serve import flask_app serve(flask_app.app, host='0.0.0.0', port=8080, url_scheme='https') .. note:: Specifying the proper host, port and url_scheme is crucial. .. tip:: To check which services are running use: `sudo service --status-all` Create a service with systemd to run the server at startup ========================================================== In order to automatically run the Web server at each startup, we can create a service with systemd: source: https://linuxconfig.org/how-to-autostart-python-script-on-raspberry-pi .. note:: All service files are located in `/etc/systemd/system` .. code-block:: bash user@pi:/etc/systemd/system $ ls bluetooth.target.wants graphical.target.wants cloudflared.service halt.target.wants cloudflared-update.service jenkins.service.d cloudflared-update.timer multi-user.target.wants dbus-fi.w1.wpa_supplicant1.service network-online.target.wants dbus-org.bluez.service poweroff.target.wants dbus-org.freedesktop.Avahi.service printer.target.wants dbus-org.freedesktop.ModemManager1.service reboot.target.wants dbus-org.freedesktop.nm-dispatcher.service remote-fs.target.wants dbus-org.freedesktop.timesync1.service runwaitress.service default.target sockets.target.wants dev-serial1.device.wants sshd.service display-manager.service sysinit.target.wants getty.target.wants timers.target.wants getty@tty1.service.d wayvnc.service.wants .. code-block:: bash user@pi:/etc/systemd/system $ cat runwaitress.service [Unit] Description=Run production server with Waitress After=multi-user.target [Service] Type=oneshot ExecStart=/home/user/virtEnv/Website/bin/python /home/user/myApp/waitress_server.py --serve-in-foreground [Install] WantedBy=multi-user.target Apply the appropriate permissions to the file so that systemd can execute it. Afterwards, we will apply the proper permissions to the systemd timer file. .. code-block:: bash $ sudo chmod 744 myApp/waitress_server.py $ sudo chmod 664 /etc/systemd/system/runwaitress.service Next, enable the service unit: .. code-block:: bash $ sudo systemctl daemon-reload $ sudo systemctl enable runwaitress.service Common pitfalls =============== Issues encountered and how they have been fixed. Python OSError: [Errno 98] Address already in use ------------------------------------------------- The Python error "OSError: [Errno 98] Address already in use" occurs when you have another process running on the specified port. You can resolve the error by using the SO_REUSEADDR attribute or by identifying and stopping the process before you start your server. To get the process ID of the process that is running on the specified port, use the `lsof` command. .. code-block:: bash $ sudo lsof -i :8081 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME python 1931 root 6u IPv4 9077 0t0 TCP *:tproxy (LISTEN) The PID column contains the ID of the process that is running on the specified port. You can stop the process by issuing the kill command. .. code-block:: bash $ sudo kill -9