Categorygithub.com/wehw93/http-rest-api
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.