repository
0.0.0-20250103213332-8a5f21f4c9c1
Repository: https://github.com/wehw93/http-rest-api.git
Documentation: pkg.go.dev
# Packages
No description provided by the author
# README
Описание проекта
В этом проекте я практиковался с REST-API.
Сборка
- Для сборки исполняемого файла используется команда
make
.
Конфигурация
- apiserver конфигурируется с помощью конфигурационного файла в формате
toml
. - Для парсинга конфигурационного файла используется зависимость
BurntSushi
.
Логирование
- Для логирования используется зависимость
logrus
. - Для настройки уровня логирования реализована функция
configureLogger
. - Уровень логирования задаётся в конфигурационном файле.
HTTP-сервер
- В качестве роутера для HTTP-сервера используется пакет
gorilla/mux
. - Для описания роутов реализована функция
configureRouter
.
Тестирование
- Для тестирования функций используется зависимость
stretchr/testify
.
Работа с базой данных
- В проекте используется база данных PostgreSQL.
- Для работы с БД используется стандартный пакет
database/sql
. - Строка подключения парсится из конфигурационного файла в формате
toml
. - Пакет
golang-migrate
используется для написания и применения миграций. - Основная идея: реализовать хранилище, которое скрывает детали работы с БД и предоставляет публичные методы для взаимодействия.
Репозитории и модели данных
- Хранилище состоит из нескольких репозиториев.
- В пакете
model
хранятся структуры, являющиеся представлениями в базе данных (модели данных). - Поля структур соответствуют схемам в БД.
- За взаимодействие с БД отвечают репозитории в директории
store
.
Работа с репозиториями
- Для работы с репозиторием
User
извне создан методUser
, через который происходит взаимодействие с БД.
Тестирование БД
- Создан файл
testing.go
, который:- Возвращает тестовое хранилище, настроенное для тестирования.
- Предоставляет функцию для очистки тестового хранилища, чтобы каждый тест запускался с чистой базой данных.
Рефакторинг
- На данном этапе обнаружил 2 основыне проблемы моего приложения:
- Структура веб сервера достаточно закрытая и инициализация всех зависимостей происходит внутри самой структуры, поэтому мы не имеем возможности подменять зависимости например в тестах. В тестах я бы хотел подменять хранилище на мапу, а реальные запросы к базе данных использовать только при тестировании непосредственно самого хранилища.
- Хранилище на данном этапе имеет реализацию в виде структуры и мы не можем просто так взять и прокинуть в наш сервер другой хранилище,для этого нужно использовать в сервере не конкретный тип хранилища, а интерфейс, его нужно реализовать.
- Создал 2 пакета:
sqlstore
для тестирования на реальном хранилище,teststore
для тестирования на фейковом хранилище, в данном случае мапа.
Стандартизация ошибок
- После рефакторинга я понял, что тесты реального хранилища и мнимого возвращают разные ошибки, я бы хотел их стандартизировать, для этого создал файл errors.go в котором реализуем общие конкретные ошибки, внедрим их в наши тесты.
Регистрация и аутентификация
- для этого добавим 2 ендпоинта:
- один будет регситрировать пользователя, создавать его в базе данных.
- второй будем проверять входящий email и пароль, и если все хорошо отдавать в ответе сессионную cookie заголовков
- тестирование в файле
server_internal_test.go
- по
REST-API
криейты всегда отвечают наPOST
запросы
Регистрация
- создал новый роут
"/users"
- обработчик:
handleUsersCreate
. Пользователь вводит созданный нами типrequest
, включает в себя email, password. С помощью пакетаjson
декодируем данные из запроса в нашrequest
. В случае ошибки вызываем хелперerror
, со статусомStatusBadRequset
. - Создал функцию
Sanitise
, эта функция будет затирать те атрибуты, которые мы считаем приватными, в данном случае пароль.
Аутентификация
- создал новый роут
"/sessions"
- функция обработчик
handleSessionsCreate
. Типrequset
включает в себя также email, password. Так как при аутентификации нам нужно сравнить пароль из базы данных с паролем, введенным пользователем, а пароль в бд хранится в зашифрованном виде, для этого мы создадим хелпер функциюuserComparePassword
, в ней воспользуемся пакетомbcrypt
, а именно функциейCompareHashAndPassword
. - Если пользтватель не найден, вызываем хелпер
error
, со статусомStatusUnautorized
, в качестве ошибки передадим нашу переменнуюerrIncrorrectEmailorPassword
, чтобы злоумышлинники не могли получить лишней информации. - Для работы с сессионными cookie воспользуемся пакетом
gorilla/sessions
.