API и go_core_query
В системе GoCore предусмотрено два основных способа взаимодействия с API: через стандартные HTTP(s) запросы и через постоянное соединение по сокетам с использованием специализированной библиотеки go_core_query.
API. Доступ по http(s)
Авторизация
Для работы с API необходимо сначала выполнить запрос авторизации (User.login). В ответ сервер возвращает JWT-токен, который должен передаваться в заголовке Authorization для всех последующих запросов:
Authorization: Bearer <Token>
Если сессия просрочена или аннулирована, сервер вернет стандартный объект ответа (IAPIResponse) с кодом -4.
Подробнее см. разделы Система кэширования и Документирование.
Формат запросов
Все запросы к API (включая получение данных) отправляются методом POST. Это позволяет скрыть параметры запроса от злоумышленников и провайдеров.
URL запроса строится по шаблону: /api/v1/:className/:command
- className: имя класса (можно указывать с маленькой буквы).
- command: имя вызываемого метода.
Пример (User.login):
URL: /api/v1/user/login
Тело запроса: JSON-объект с параметрами (например, login и password).
Пример curl:
curl -X 'POST' \
'http://127.0.0.1:7011/api/v1/user/login' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"password": "qwerty",
"login": "admin"
}'
Автоматическая документация
Документация для методов API генерируется автоматически на основе декораторов в коде.
- Попробовать методы в интерактивном режиме:
/api-docs - Скачать OpenAPI спецификацию:
/api-docs/download
Доступ по сокету
Самостоятельное подключение
Соединение использует библиотеку socket.io (актуальная версия на момент написания — 4.6.1). Хотя самостоятельное подключение возможно, оно содержит ряд нюансов. В большинстве случаев рекомендуется использовать готовую библиотеку go_core_query.
Библиотека go_core_query
Это специализированная библиотека для работы с GoCore через сокеты. Она доступна через npm:
npm i go_core_query
Встроенный в ядро фронтенд использует именно ее.
Основные возможности
- Автоматическая передача данных клиента (например, часовой пояс).
- Управление токенами и их сохранение в хранилище.
- Автоматическая авторизация и переавторизация при потере сессии (актуально для подключений из другого сервиса (бэк - бэк)).
- Отслеживание состояния подключения и автоматические переподключения с настроенными таймингами.
- Обработка серверных запросов на перенаправление пользователя (например, на страницу логина).
- Удобный интерфейс для отправки запросов к API (аналогично
fetch). - Логирование запросов в консоль (в режиме debug).
Библиотека поддерживает различные окружения: браузер (включая старые версии через <script>), Node.js, React Native.
Использование и инициализация
Основная точка входа — функция initGoCoreQuery. Она возвращает объект с двумя полями:
- api: асинхронная функция для выполнения запросов. Принимает
IAPIQuery, возвращаетPromise<IAPIResponse>. - instance: инстанс класса
Query, через который можно получить доступ к самому сокету и другим внутренним свойствам.
Для подписки на события сокета обычно используется параметр afterInitConnect: (socket: Socket) => void.
Пример подключения (React)
Ниже приведен пример реализации модуля для работы с API в React-приложении:
// @ts-ignore
import initGoCoreQuery from "go_core_query";
import { Socket } from "socket.io-client";
import { IAPIResponse } from "./structure";
export let api: (o: Record<string, any>) => Promise<IAPIResponse> = async (o) => {
console.log("GoCoreContextAPIFn is not ready now. Request will be repeated after short pause");
await new Promise<void>(cb => setTimeout(cb, 500));
return await api(o);
};
export let goCoreQueryInstance = {};
// ... (обработчики-заглушки для emit, socketOn, socketOff)
export const initGoCoreAPI = async (params: Record<string, any> = {}) => {
const { afterInitConnect, setIsAuth, socketOnConnect, socketOnDisconnect, socketOnError } = params;
// Настройка Debug режима через куки
let debugCookie = document.cookie.match(/debugGoCoreAPI=(\w+)/);
let debug = debugCookie ? debugCookie[1] === "true" : false;
const config = {
host: import.meta.env.VITE_APP_HOST,
port: import.meta.env.VITE_APP_PORT,
https: import.meta.env.VITE_APP_HTTPS === "true",
login: import.meta.env.VITE_APP_LOGIN,
password: import.meta.env.VITE_APP_PASSWORD,
autoAuth: import.meta.env.VITE_APP_AUTO_AUTH === "true",
useAJAX: false,
tokenStorageKey: "ProjectToken",
debug,
authFn: (_obj: any, cb: Function) => {
if (typeof setIsAuth === "function") {
setIsAuth(false);
if (typeof cb === "function") cb(null);
}
},
afterInitConnect: (socket: Socket) => {
if (typeof afterInitConnect === "function") afterInitConnect(socket);
socket.on("connect", () => {
if (typeof socketOnConnect === "function") socketOnConnect(socket);
// Переопределение функций-заглушек реальными методами сокета
// api = socketQueryOriginal.api;
});
socket.on("disconnect", () => {
if (typeof socketOnDisconnect === "function") socketOnDisconnect(socket);
});
},
};
const socketQueryOriginal = initGoCoreQuery(config);
api = socketQueryOriginal.api;
goCoreQueryInstance = socketQueryOriginal.instance;
};
Основные параметры подключения
- host, port, https: Параметры сервера. Важно: неверное указание протокола (https) может привести к отсутствию внятных ошибок при невозможности подключения.
- autoAuth: Если
true, библиотека сама выполнит авторизацию (обычно используется для серверных подключений). Для фронтенда рекомендуетсяfalse. - authFn: Callback, вызываемый при необходимости авторизации (например, редирект на
/login). - useAJAX: Позволяет библиотеке работать через
fetchвместо сокетов. - tokenStorageKey: Ключ для хранения токена в LocalStorage.
- debug, debugFull: Режимы логирования.
debugFullвыводит детальную информацию о внутренних состояниях библиотеки.
Вызов методов из консоли
Во встроенном в ядро интерфейсе, api доступно как глобальная переменная, а следовательно ее можно использовать прямо из консоли браузера (DevTools). Чтобы запрос был авторизован, сперва авторизируйтесь в интерфейсе. Далее заголовок авторизации будет подключаться автоматически при установке соединения сокета. Пример использования:
api({
command: 'getMe',
object: 'User'
})