/
murodovjaha
/
Cursor
Обзор
Документация
Войти
/
murodovjaha
/
Cursor
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/http_server.py
339 строк
12 KB
Murodov Jahongir
Заменён простой сервер на продвинутый с POST, API и формой
24 май 2026, 18:56
24 май 2026, 18:56
335e450
Код
Авторство
О чём код?
""" Продвинутый HTTP-сервер на Python Поддерживает GET, POST, статические файлы, форму обратной связи """ from http.server import HTTPServer, BaseHTTPRequestHandler import urllib.parse import json import os # Файл для хранения сообщений MESSAGES_FILE = 'messages.json' # Инициализация файла сообщений if not os.path.exists(MESSAGES_FILE): with open(MESSAGES_FILE, 'w', encoding='utf-8') as f: json.dump([], f) # Счётчик посещений counter = 0 class AdvancedHTTPHandler(BaseHTTPRequestHandler): def do_GET(self): """Обработка GET-запросов""" global counter parsed_path = urllib.parse.urlparse(self.path) # Главная страница if parsed_path.path == '/': counter += 1 self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() html = f''' <!DOCTYPE html> <html> <head> <title>Cursor Advanced Server</title> <meta charset="utf-8"> <link rel="stylesheet" href="/style.css"> </head> <body> <div class="container"> <h1>🚀 Cursor Advanced HTTP-сервер</h1> <p>Продвинутая версия с поддержкой POST и статических файлов</p> <div class="counter"> Посещений: {counter} </div> <h2>📝 Форма обратной связи</h2> <form action="/submit" method="POST"> <input type="text" name="name" placeholder="Ваше имя" required> <textarea name="message" placeholder="Ваше сообщение" required></textarea> <button type="submit">Отправить</button> </form> <h2>💬 Сообщения</h2> <div id="messages"> <!-- Сообщения подгрузятся через API --> </div> <div class="links"> <a href="/about">О сервере</a> <a href="/api/messages">API: сообщения</a> <a href="/status">Статус</a> </div> </div> <script> fetch('/api/messages') .then(res => res.json()) .then(data => {{ const container = document.getElementById('messages'); if (data.length === 0) {{ container.innerHTML = '<p>Нет сообщений. Будьте первым!</p>'; }} else {{ container.innerHTML = data.map(msg => `<div class="message"><strong>${{msg.name}}</strong><p>${{msg.message}}</p></div>` ).join(''); }} }}); </script> </body> </html> ''' self.wfile.write(html.encode('utf-8')) # Страница "О сервере" elif parsed_path.path == '/about': self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() html = ''' <!DOCTYPE html> <html> <head> <title>О сервере</title> <meta charset="utf-8"> <link rel="stylesheet" href="/style.css"> </head> <body> <div class="container"> <h1>📖 О сервере</h1> <p>Продвинутый HTTP-сервер, разработанный в рамках проектной практики "Cursor".</p> <h2>Возможности:</h2> <ul> <li>✅ GET и POST запросы</li> <li>✅ Отдача статических файлов (CSS)</li> <li>✅ Форма обратной связи</li> <li>✅ Хранение данных в JSON-файле</li> <li>✅ JSON API (/api/messages)</li> <li>✅ Счётчик посещений</li> </ul> <p><a href="/">← На главную</a></p> </div> </body> </html> ''' self.wfile.write(html.encode('utf-8')) # Статус в JSON elif parsed_path.path == '/status': self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() status = { "status": "running", "server": "Cursor Advanced HTTP Server", "version": "2.0", "visits": counter, "messages_count": self.get_messages_count() } self.wfile.write(json.dumps(status, indent=4, ensure_ascii=False).encode('utf-8')) # API: получить все сообщения elif parsed_path.path == '/api/messages': self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() with open(MESSAGES_FILE, 'r', encoding='utf-8') as f: messages = json.load(f) self.wfile.write(json.dumps(messages, ensure_ascii=False).encode('utf-8')) # Статические файлы (CSS) elif parsed_path.path == '/style.css': self.send_response(200) self.send_header('Content-type', 'text/css') self.end_headers() css = ''' * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 20px; } .container { max-width: 800px; margin: 0 auto; background: white; border-radius: 15px; padding: 30px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); } h1 { color: #667eea; margin-bottom: 10px; } h2 { color: #764ba2; margin-top: 25px; margin-bottom: 15px; } .counter { background: #667eea; color: white; padding: 10px; border-radius: 8px; text-align: center; margin: 20px 0; font-size: 1.2em; } form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; } input, textarea { padding: 10px; border: 1px solid #ddd; border-radius: 8px; font-size: 16px; } textarea { min-height: 100px; resize: vertical; } button { background: #667eea; color: white; border: none; padding: 12px; border-radius: 8px; cursor: pointer; font-size: 16px; } button:hover { background: #5a67d8; } .message { background: #f7f7f7; padding: 15px; border-radius: 8px; margin-bottom: 10px; } .message strong { color: #667eea; } .links { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; text-align: center; } .links a { margin: 0 10px; color: #667eea; text-decoration: none; } .links a:hover { text-decoration: underline; } ul { margin-left: 20px; margin-top: 10px; } li { margin: 8px 0; } p { margin-top: 10px; } ''' self.wfile.write(css.encode('utf-8')) else: self.send_response(404) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() self.wfile.write(b'<h1>404 Not Found</h1><p>Document not found</p>') def do_POST(self): """Обработка POST-запросов""" parsed_path = urllib.parse.urlparse(self.path) if parsed_path.path == '/submit': content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length).decode('utf-8') form_data = urllib.parse.parse_qs(post_data) name = form_data.get('name', [''])[0] message = form_data.get('message', [''])[0] if name and message: with open(MESSAGES_FILE, 'r', encoding='utf-8') as f: messages = json.load(f) messages.append({ 'name': name, 'message': message, 'timestamp': self.get_timestamp() }) with open(MESSAGES_FILE, 'w', encoding='utf-8') as f: json.dump(messages, f, ensure_ascii=False, indent=2) self.send_response(303) self.send_header('Location', '/') self.end_headers() def get_messages_count(self): with open(MESSAGES_FILE, 'r', encoding='utf-8') as f: messages = json.load(f) return len(messages) def get_timestamp(self): from datetime import datetime return datetime.now().strftime('%Y-%m-%d %H:%M:%S') def log_message(self, format, *args): print(f"[{self.address_string()}] {args[0]}") def run_server(port=8080): server_address = ('', port) httpd = HTTPServer(server_address, AdvancedHTTPHandler) print(f'🚀 Cursor Advanced HTTP-сервер запущен на порту {port}') print(f'📱 Откройте в браузере: http://localhost:{port}') print(f'💾 Сообщения сохраняются в {MESSAGES_FILE}') print('🛑 Нажмите Ctrl+C для остановки\n') try: httpd.serve_forever() except KeyboardInterrupt: print('\n👋 Сервер остановлен') httpd.server_close() if __name__ == '__main__': run_server(8080)