Как веб-сервер обрабатывает входящий HTTP GET-запрос?

«Как веб-сервер обрабатывает входящий HTTP GET-запрос?» — вопрос из категории Сети, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Обработка GET-запроса проходит через несколько уровней стеков TCP/IP и HTTP. Рассмотрим на примере запроса GET /api/users?id=123 HTTP/1.1.

1. Сетевой уровень (TCP/IP):

  • Клиент устанавливает TCP-соединение через трехстороннее рукопожатие (SYN, SYN-ACK, ACK)
  • Данные передаются сегментами с контролем перегрузки и подтверждением получения

2. Уровень веб-сервера (Nginx/Apache):

# Конфигурация Nginx для маршрутизации
server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        # Проксирование на backend-приложение
        proxy_pass http://backend:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3. Уровень приложения (Backend):

# Пример обработки в Python/Flask
from flask import Flask, request, jsonify
import json

app = Flask(__name__)

@app.route('/api/users', methods=['GET'])
def get_user():
    # Извлечение параметра из query string
    user_id = request.args.get('id', type=int)

    # Валидация входных данных
    if not user_id:
        return jsonify({'error': 'ID is required'}), 400

    # Бизнес-логика и работа с БД
    user = database.get_user_by_id(user_id)

    if not user:
        return jsonify({'error': 'User not found'}), 404

    # Формирование ответа
    return jsonify({
        'id': user.id,
        'name': user.name,
        'email': user.email
    })

# Запуск сервера
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9000)

4. Обработка query parameters:

  • Параметры извлекаются из URL после ?
  • Формат: ключ=значение, разделенные &
  • Пример: /search?q=python&page=2&sort=date
  • Ограничение длины зависит от браузера и сервера (обычно 2048+ символов)

5. Формирование HTTP-ответа:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 85
Connection: keep-alive
Cache-Control: max-age=3600

{"id": 123, "name": "John Doe", "email": "john@example.com"}

Безопасность:

  • Всегда валидируйте и санитизируйте входные данные
  • Используйте HTTPS для шифрования трафика
  • Ограничивайте размер запросов и rate limiting