Настроить Nginx в качестве HTTPS-прокси для вашего REST приложения Python на Flask и Waitress на Ubuntu
#24 вторник, 18 июля 2023 г. 12 минут(ы) 1084 слова
Настройка Nginx
Вам нужно настроить Nginx, чтобы использовать SSL и перенаправлять запросы на ваше приложение Flask.
Если вы используете файл /etc/nginx/sites-available/default, добавьте следующий server для нужного поддомена например api.pixelrobot.ru:
server {
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name api.pixelrobot.ru; # managed by Certbot
location / {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Port $server_port;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pixelrobot.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pixelrobot.ru/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
Давайте разберем каждую директиву внутри блока "location":
-
proxy_pass http://localhost:5000; Эта директива указывает адрес бэкэнд-сервера https://api.pixelrobot.ru/, на который будут перенаправляться входящие запросы.
-
proxy_set_header Host $host; Эта директива устанавливает заголовок "Host" в перенаправляемом запросе со значением из исходного заголовка "Host". Она обеспечивает передачу правильного имени хоста на бэкэнд-сервер.
-
proxy_set_header X-Real-IP $remote_addr; Эта директива устанавливает заголовок "X-Real-IP" в перенаправляемом запросе со значением IP-адреса клиента, совершающего запрос. Она может быть полезна для логирования или определения IP-адреса клиента на бэкэнд-сервере.
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; Эта директива устанавливает заголовок "X-Forwarded-For" в перенаправляемом запросе. Если заголовок "X-Forwarded-For" уже присутствует, то она добавляет IP-адрес клиента к существующему значению. Этот заголовок обычно используется для отслеживания исходного IP-адреса клиента при прохождении через промежуточные прокси.
-
proxy_set_header X-Forwarded-Host $host:$server_port; Эта директива устанавливает заголовок "X-Forwarded-Host" в перенаправляемом запросе со значением из исходного заголовка "Host", за которым следует номер порта сервера.
-
proxy_set_header X-Forwarded-Port $server_port; Эта директива устанавливает заголовок "X-Forwarded-Port" в перенаправляемом запросе со значением номера порта сервера.
Вместе эти директивы настраивают обратный прокси для передачи оригинального запроса на бэкэнд-сервер, указанный как http://localhost:5000, с сохранением соответствующих заголовков для правильной работы и идентификации.
В этой конфигурации все запросы HTTP перенаправляются на HTTPS, а запросы HTTPS передаются на ваше приложение Flask, которое, как предполагается, работает на порту 5000.
Перезапуск Nginx
Сначала проверим, все ли изменения в конфигурации Nginx были сделаны правильно:
sudo nginx -t
Если все в порядке, перезапустите Nginx:
sudo nginx -s reload
Простое приложение на Python, Flask и Waitress
Вот пример простого REST приложения на Flask и Waitress.
Сначала установим необходимые библиотеки через pip, в среде выполнения python3:
pip install flask waitress
Далее, создадим простое Flask приложение с одним маршрутом:
#get.py
from flask import Flask, request, jsonify
from waitress import serve
app = Flask(__name__)
@app.route('/get', methods=['GET'])
def get():
# Access URL parameters with request.args
name = request.args.get('name')
age = request.args.get('age')
if name and age:
print(f"Received data: Name - {name}, Age - {age}")
return "Data received and processed", 200
else:
return "No data received", 400
#if __name__ == '__main__':
# app.run(debug=True)
if __name__ == "__main__":
#app.run(host='0.0.0.0',port=5000)
#We now use this syntax to server our app.
#serve(app, host='0.0.0.0', port=5000)
serve(app, host='0.0.0.0', port=5000, url_scheme='https')
# C:\curl\curl "https://api.pixelrobot.ru/get?name=John&age=30"
Это пример приложения слушает на порту 5000 и возвращает приветственное сообщение при обращении к маршруту '/get'.
Вы можете запустить приложение из командной строки:
python app.py
Теперь, при переходе на https://api.pixelrobot.ru/get?name=John&age=30, вы получите ответ Data received and processed.
А в терминале на сервере будет выведен текст:
(env311) d00m4ace@server:~/projects/python$ python3 get.py
Received data: Name - John, Age - 30
Если вы хотите добавить больше маршрутов или функциональности, вы можете сделать это, добавив больше маршрутов и функций в ваше приложение Flask.
REST приложение на Python, Flask и Waitress
Мы определим несколько базовых REST маршрутов, которые будут возвращать некоторые данные в формате JSON.
# app.py
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api/tasks', methods=['GET'])
def get_tasks():
tasks = [
{"id": 1, "title": "Buy groceries", "completed": False},
{"id": 2, "title": "Study for test", "completed": True},
]
return jsonify(tasks)
@app.route('/api/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
tasks = [
{"id": 1, "title": "Buy groceries", "completed": False},
{"id": 2, "title": "Study for test", "completed": True},
]
for task in tasks:
if task["id"] == task_id:
return jsonify(task)
return jsonify({"error": "Task not found"}), 404
if __name__ == '__main__':
from waitress import serve
serve(app, host="0.0.0.0", port=5000)
В этом примере мы имеем два маршрута. Один для получения всех задач (GET /api/tasks), и один для получения конкретной задачи по её id (GET /api/tasks/
Мы используем waitress для запуска нашего приложения. Это production-ready WSGI сервер, который рекомендован для использования с Flask в production.
Для запуска приложения используйте команду:
python app.py
Теперь приложение будет слушать на порту 5000 и будет доступно по адресу https://api.pixelrobot.ru/api/tasks и https://api.pixelrobot.ru/api/tasks/
POST приложение на Python, Flask и Waitress
Сначала установим необходимые библиотеки через pip:
pip install flask waitress
Flask приложение на Python обрабатывает разные типы входящих данных:
# app.py
from flask import Flask, request, jsonify
from waitress import serve
app = Flask(__name__)
#app.config['SECRET_KEY'] = 'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'
@app.route('/post', methods=['POST'])
def post():
if request.is_json:
# For JSON data, use request.get_json()
data = request.get_json()
print(f"Received JSON data: {data}")
elif request.headers['Content-Type'] == 'application/x-www-form-urlencoded':
# For form data, use request.form
data = request.form
print(f"Received form data: {data}")
else:
# For plain text, use request.data
data = request.data.decode('utf-8')
print(f"Received plain text data: {data}")
return "Data received and processed", 200
#if __name__ == '__main__':
# app.run(debug=True)
if __name__ == "__main__":
serve(app, host='0.0.0.0', port=5000, url_scheme='https')
Для запуска приложения используйте команду:
python app.py
С помощью команды curl отправим POST запрос с JSON данными на конечную точку /post по указанному URL.
C:\curl\curl -X POST -H "Content-Type: application/json" -d "{\"name\":\"John\", \"age\":30}" https://api.pixelrobot.ru/post
Заголовок "Content-Type: application/json" сообщает серверу, что клиент (в данном случае curl) отправляет данные в формате JSON. Это позволяет серверу правильно интерпретировать и обрабатывать отправленные данные.
В контексте Flask приложения, когда вы делаете POST запрос и указываете "Content-Type: application/json", Flask знает, что ему следует получить данные из request.get_json().
C:\curl\curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "name=John&age=30" https://api.pixelrobot.ru/post
Эта команда curl отправляет POST запрос с данными, закодированными как application/x-www-form-urlencoded, на конечную точку /post по указанному URL.
Формат "application/x-www-form-urlencoded" обычно используется при отправке данных формы HTML. В этом формате, пары имя/значение записываются как name=value, с разделением пар амперсандом (&).
В контексте Flask приложения, когда вы делаете POST запрос и указываете "Content-Type: application/x-www-form-urlencoded", Flask будет искать данные в request.form.
C:\curl\curl -X POST -H "Content-Type: text/plain" -d "Hello, World!" https://api.pixelrobot.ru/post
Эта команда curl отправляет POST запрос с данными в формате text/plain на конечную точку /post по указанному URL.
Формат text/plain используется для отправки обычного текста. В данном случае, вы отправляете строку "Hello, World!".
В контексте Flask приложения, когда вы делаете POST запрос и указываете "Content-Type: text/plain", Flask будет искать данные в request.data.
Ваш URL https://api.pixelrobot.ru/post в этом примере должен быть заменен на реальный URL вашего сервера.