forked from netology-code/shvirtd-example-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
158 lines (130 loc) · 6.17 KB
/
main.py
File metadata and controls
158 lines (130 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from datetime import datetime
import os
from contextlib import contextmanager, asynccontextmanager
import mysql.connector
from fastapi import FastAPI, Request, Depends, Header
from typing import Optional
# --- 1. Конфигурация ---
# Считываем конфигурацию БД из переменных окружения
db_host = os.environ.get('DB_HOST', '127.0.0.1')
db_user = os.environ.get('DB_USER', 'app')
db_password = os.environ.get('DB_PASSWORD', 'very_strong')
db_name = os.environ.get('DB_NAME', 'example')
# ### <--- ИЗМЕНЕНО: Добавляем чтение имени таблицы из ENV
table_name = os.environ.get('TABLE_NAME', 'requests')
@asynccontextmanager
async def lifespan(app: FastAPI):
# Код, который выполнится перед запуском приложения
print("Приложение запускается...")
try:
with get_db_connection() as db:
cursor = db.cursor()
# ### <--- ИЗМЕНЕНО: Используем переменную table_name при создании
create_table_query = f"""
CREATE TABLE IF NOT EXISTS {db_name}.{table_name} (
id INT AUTO_INCREMENT PRIMARY KEY,
request_date DATETIME,
request_ip VARCHAR(255)
)
"""
cursor.execute(create_table_query)
db.commit()
# ### <--- ИЗМЕНЕНО: Вывод в лог актуального имени таблицы
print(f"Соединение с БД установлено и таблица '{table_name}' готова к работе.")
cursor.close()
except mysql.connector.Error as err:
print(f"Ошибка при подключении к БД или создании таблицы: {err}")
yield
# Код, который выполнится при остановке приложения
print("Приложение останавливается.")
# Создаем экземпляр FastAPI с использованием lifespan
app = FastAPI(
title="Shvirtd Example FastAPI",
description="Учебный проект, FastAPI+Docker.",
version="1.0.0",
lifespan=lifespan
)
# --- 2. Управление соединением с БД ---
@contextmanager
def get_db_connection():
db = None
try:
db = mysql.connector.connect(
host=db_host,
user=db_user,
password=db_password,
database=db_name
)
yield db
finally:
if db is not None and db.is_connected():
db.close()
# --- 3. Зависимость для получения IP ---
def get_client_ip(x_real_ip: Optional[str] = Header(None)):
return x_real_ip
# --- 5. Основной эндпоинт ---
@app.get("/")
def index(request: Request, ip_address: Optional[str] = Depends(get_client_ip)):
final_ip = ip_address # Только из X-Forwarded-For, без fallback
now = datetime.now()
current_time = now.strftime("%Y-%m-%d %H:%M:%S")
try:
with get_db_connection() as db:
cursor = db.cursor()
# ### <--- ИЗМЕНЕНО: Используем переменную table_name при вставке
query = f"INSERT INTO {table_name} (request_date, request_ip) VALUES (%s, %s)"
values = (current_time, final_ip)
cursor.execute(query, values)
db.commit()
cursor.close()
except mysql.connector.Error as err:
return {"error": f"Ошибка при работе с базой данных: {err}"}
# Подсказка для студентов при неправильном обращении
if final_ip is None:
ip_display = "похоже, что вы направляете запрос в неверный порт(например curl http://127.0.0.1:5000). Правильное выполнение задания - отправить запрос в порт 8090."
else:
ip_display = final_ip
return f'TIME: {current_time}, IP: {ip_display}'
# --- 5. Отладочный эндпоинт ---
@app.get("/debug")
def debug_headers(request: Request):
"""Показывает все заголовки для отладки откуда берется IP"""
return {
"headers": dict(request.headers),
"client_host": request.client.host if request.client else None,
"x_forwarded_for": request.headers.get('x-forwarded-for'),
"real_ip": request.headers.get('x-real-ip'),
"forwarded": request.headers.get('forwarded')
}
# --- 6. Эндпоинт для просмотра записей в БД ---
@app.get("/requests")
def get_requests():
"""Возвращает все записи из таблицы requests для проверки"""
try:
with get_db_connection() as db:
cursor = db.cursor()
# ### <--- ИЗМЕНЕНО: Используем переменную table_name при выборке
query = f"SELECT id, request_date, request_ip FROM {table_name} ORDER BY id DESC LIMIT 50"
cursor.execute(query)
records = cursor.fetchall()
cursor.close()
# Преобразуем записи в читабельный формат
result = []
for record in records:
result.append({
"id": record[0],
"request_date": record[1].strftime("%Y-%m-%d %H:%M:%S") if record[1] else None,
"request_ip": record[2]
})
return {
"total_records": len(result),
"records": result
}
except mysql.connector.Error as err:
return {"error": f"Ошибка при чтении из базы данных: {err}"}
# --- 7. Запуск приложения ---
# Для запуска этого файла используется ASGI-сервер, например, uvicorn.
# Команда: uvicorn main:app --reload
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=5000)