/
dashaaaa12234
/
team-project-practice
Обзор
Документация
Войти
/
dashaaaa12234
/
team-project-practice
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/http_server/server.py
208 строк
6 KB
Богданова Дарья
Обновил HTTP-сервер: добавил API, логирование, обработку 404
23 май 2026, 18:43
23 май 2026, 18:43
115e3e7
Код
Авторство
О чём код?
import socket import threading import os from datetime import datetime import json HOST = '127.0.0.1' PORT = 8080 BASE_DIR = 'static' # Создаём папку для статики, если её нет if not os.path.exists(BASE_DIR): os.makedirs(BASE_DIR) # Создаём папку для логов if not os.path.exists('logs'): os.makedirs('logs') # Создаём пример HTML-страницы (без русских букв в байтах) index_html = '''<!DOCTYPE html> <html> <head><title>My HTTP Server</title> <style> body { font-family: Arial; text-align: center; margin-top: 50px; } button { padding: 10px 20px; margin: 10px; cursor: pointer; } #time { font-size: 24px; color: blue; } </style> </head> <body> <h1>HTTP Server is running!</h1> <p>This file is loaded from static/ folder</p> <button onclick="getTime()">Get Time</button> <p id="time"></p> <button onclick="location.href='/about'">About Server</button> <button onclick="location.href='/api/time'">API: Time</button> <script> async function getTime() { const res = await fetch('/api/time'); const data = await res.json(); document.getElementById('time').innerText = data.time; } </script> </body> </html>''' about_html = '''<!DOCTYPE html> <html> <head><title>About Server</title> <style>body { font-family: Arial; text-align: center; margin-top: 50px; }</style> </head> <body> <h1>About HTTP Server</h1> <p>Version: 2.0</p> <p>Protocol: HTTP/1.1</p> <p>Multithreading: Yes</p> <p>Logging: On</p> <p><a href="/">Back to Home</a></p> </body> </html>''' # Записываем HTML файлы with open(f'{BASE_DIR}/index.html', 'w', encoding='utf-8') as f: f.write(index_html) with open(f'{BASE_DIR}/about.html', 'w', encoding='utf-8') as f: f.write(about_html) def log_request(method, path, status, ip): """Запись запроса в лог-файл""" with open('logs/access.log', 'a', encoding='utf-8') as log: log.write(f"{datetime.now()} | {ip} | {method} {path} | {status}\n") def serve_file(path): """Отдаёт файл из папки static""" if path == '/': path = '/index.html' filepath = f'{BASE_DIR}{path}' # Определяем тип файла if path.endswith('.html'): content_type = 'text/html; charset=utf-8' elif path.endswith('.css'): content_type = 'text/css' elif path.endswith('.js'): content_type = 'application/javascript' else: content_type = 'text/plain; charset=utf-8' try: with open(filepath, 'rb') as f: content = f.read() response = f'HTTP/1.1 200 OK\r\n' response += f'Content-Type: {content_type}\r\n' response += f'Content-Length: {len(content)}\r\n' response += 'Connection: close\r\n' response += '\r\n' return response.encode() + content, 200 except FileNotFoundError: return None, 404 def handle_api(uri): """Обрабатывает API-запросы""" if uri == '/api/time': data = { 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'timestamp': int(datetime.now().timestamp()) } body = json.dumps(data, ensure_ascii=False).encode('utf-8') response = f'HTTP/1.1 200 OK\r\n' response += 'Content-Type: application/json; charset=utf-8\r\n' response += f'Content-Length: {len(body)}\r\n' response += 'Connection: close\r\n' response += '\r\n' return response.encode() + body, 200 return None, 404 def handle_404(): """Страница 404 Not Found""" body = '''<!DOCTYPE html> <html> <head><title>404 Not Found</title> <style>body { font-family: Arial; text-align: center; margin-top: 100px; }</style> </head> <body> <h1>404 - Page Not Found</h1> <p>The requested page does not exist</p> <a href="/">Back to Home</a> </body> </html>'''.encode('utf-8') response = f'HTTP/1.1 404 Not Found\r\n' response += 'Content-Type: text/html; charset=utf-8\r\n' response += f'Content-Length: {len(body)}\r\n' response += 'Connection: close\r\n' response += '\r\n' return response.encode() + body def handle_client(client_socket, address): """Обрабатывает одного клиента""" ip = address[0] print(f"[+] Connected: {ip}") try: request = client_socket.recv(4096).decode('utf-8', errors='ignore') if not request: return first_line = request.split('\r\n')[0] parts = first_line.split() if len(parts) >= 2: method = parts[0] path = parts[1] print(f" {method} {path}") if path.startswith('/api/'): response, status = handle_api(path) if response is None: response = handle_404() status = 404 else: content, status = serve_file(path) if content is None: response = handle_404() status = 404 else: response = content client_socket.sendall(response) log_request(method, path, status, ip) except Exception as e: print(f" Error: {e}") finally: client_socket.close() def start_server(): """Запуск сервера""" server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((HOST, PORT)) server.listen(5) print(f""" ======================================== HTTP Server Started! ======================================== Address: http://{HOST}:{PORT} Logs: logs/access.log Static: static/ ======================================== """) print("Press Ctrl+C to stop\n") while True: client, addr = server.accept() thread = threading.Thread(target=handle_client, args=(client, addr)) thread.start() if __name__ == '__main__': try: start_server() except KeyboardInterrupt: print("\n\nServer stopped")