
АВС 4 ЛР
.docx
Министерство науки и высшего образования Российской Федерации
Федеральное государственное бюджетное
образовательное учреждение высшего образования
«Уфимский университет науки и технологий»
Институт информатики, математики и робототехники
Отчёт по лабораторной работе № 4
по дисциплине «Архитектура вычислительных систем»
на тему: «Работа с протоколами прикладного уровня. Реализация HTTP веб-сервера»
Выполнил:
студент группы ПРО-332б Ихсанова Э. А.
Проверил:
преподаватель Юдинцев Б.С.
Уфа – 2024
Цель работы и задачи
Изучить примеры кода с реализацией HTTP веб-сервера, созданного на основе многопоточного сокет-сервера (см. файлы в архиве lab4_ ПРИМЕР.zip).
Добавить в веб-сервер следующие функции:
Обработка POST-запросов: запись данных в файл в папку, указанную в переменной POST_DIR, с помощью метода POST. При записи должен проверяться поддерживаемый тип контента (mime-type), а созданный файл должен иметь соответствующее расширение.
Переданные с помощью POST-метода файлы должны быть доступны для просмотра в браузере, при этом сервер должен формировать соответствующий заголовок «Content-Type» для разных типов файлов (для json, xml и html) в ответе.
Обработка основных кодов протокола HTTP, например: 400 – если был использован недопустимый HTTP-метод, 404 – если произошло обращение к несуществующей контентной странице или файлу, 500 – при возникновении ошибок/исключений сокет соединения.
При возникновении ошибок сервер должен передавать в браузер не только заголовок с соответствующим HTTP-кодом, но и контентную часть (тело) с описанием ошибки.
Ход работы
Основная работа над программой была проведена в целях реализации корректной обработки POST запросов сервером. Функция read_client_request была переработана и разбита на 3 основные части.
Первая часть является главной и отвечает за распределение запросов в зависимости от их типа.
def read_client_request(self, req): print(f'\n---------------\nClient request:\n---------------\n{req}') # Вывод запроса в консоль req_data = req.split('\r\n\r\n') # Разделение заголовка и контента head_data = req_data[0].split('\r\n') # Разделение заголовков на отдельные строки if len(head_data) > 0: # Проверка наличия заголовков main_header_data = head_data[0].split(' ') req_type = main_header_data[0] # Тип запроса (GET, POST) req_path = main_header_data[1] # Путь к запрашиваемому ресурсу if req_type == 'GET': # Если GET-запрос return self.handle_get_request(req_path) # Обработка GET-запроса elif req_type == "POST": # Если POST-запрос return self.handle_post_request(head_data, req_data) # Обработка POST-запроса return self.make_http_header(OK, 0) # Формирование HTTP-заголовка
Она может вызвать одну из двух функций, отвечающих либо за GET-запросы, либо за POST-запросы. В функции отвечающей за POST, так же реализована запись в файл.
Функция отвечающая за GET-запросы:
def handle_get_request(self, req_path): """Обработка GET-запроса""" if req_path == "/": # Если запрос к корневой директории сервера req_path = "/index.html" # Назначение индексной страницы по умолчанию return self.get_content_page(req_path) # Чтение контентной страницы
Функция отвечающая за POST-запросы:
def handle_post_request(self, head_data, req_data): content_type = None for header in head_data[1:]: # Поиск заголовка Content-Type if header.startswith("Content-Type:"): content_type = header.split(": ")[1].strip() break if content_type in MIME_TYPES and content_type: # Проверка поддерживаемого типа содержимого file_ext = content_type.split('/')[1] file_name = str(uuid.uuid4()) + '.' + file_ext file_path = os.path.join(ROOT_DIR, POST_DIR, file_name) # Формирование пути для сохранения файла with open(file_path, 'w', encoding='utf-8') as f: # Запись содержимого в файл f.write(req_data[1]) return self.make_http_header(OK, 0, content_type) + f"File saved as {file_name}" # Формирование ответа else: return self.make_http_header(BAD_REQUEST, len("Unsupported content type: " + content_type), "text/html") + "Unsupported content type: " + content_type # Формирование ответа
Суть работы всех трех функций состоит в том, что первая функция получает запрос, делит его и в зависимости от его типа, отправляет в один из двух обработчиков. Где уже формируется ответ.
Проверка работоспособности с использованием Insomnia:
Проведем тестовый GET-запрос.
Рисунок 1 – Тестовый запрос
В ответе получаем страницу нашего сайта. Все работает.
Далее проверим работоспособность программы с POST-запросом. Будет использоваться поддерживаемый формат JSON.
Рисунок 2 – JSON запрос
Далее проверка неподдерживаемого формата. Для примера возьмем YAML.
Рисунок 3 – YAML запрос
Получаем ошибку 400 Bad request. Программа работает корректно.
В конце проверим запись в файл, для этого вызовем его через GET-запрос.
Рисунок 4 – Созданный файл в WinSCP
Рисунок 5 – Сохраненный файл
Если же название файла указать некорректно, получим ошибку 404 Not Found.
Рисунок 6 – Ошибка 404
Вывод:
В ходе лабораторной работы была реализована обработка GET и POST запросов с файлами поддерживаемых расширений, а также возвращение ошибок и их описания.