Перейти к содержимому

Обзор HTTP API ​

HTTP API — это интерфейс, которым пользуются веб-консоль, клиент командной строки и SDK. Всё, что делают они, может делать ваша интеграция на любом языке. На этой странице объяснены правила, которые действуют для каждой операции. Страницы раздела Справочные страницы перечисляют каждую операцию с её правилом доступа, правилом повтора, параметрами и ответами; они создаются из контракта, который применяет сервер.

Основы ​

  • Базовый путь. Каждая операция находится под /api/v1, например https://arkvory.example/api/v1/repositories. Единственное исключение — проверки работоспособности под /health.
  • Формат. Запросы и ответы — JSON (application/json). Тело JSON ограничено 64 КиБ, а запрос с другим типом содержимого для JSON-операции получает 415. Байты файлов передаются как application/octet-stream.
  • Неизвестные поля. Большинство операций отклоняет запрос с полем, которого они не определяют (400, поле указано в details). В ответах игнорируйте поля, которых не знаете.
  • Время — метки времени RFC 3339 в UTC. Идентификаторы артефактов, загрузок, заданий, учётных записей и ключей — UUID.
  • Имена. Имя репозитория соответствует [a-z0-9][a-z0-9_-]{0,63}. Имя файла (имя артефакта) содержит до 240 символов, без / и \. Путь в репозитории содержит до 1024 символов.
  • Кэширование. Ответы содержат Cache-Control: private, no-store.
  • Другие протоколы. Маршруты /v2 (контейнеры), /lfs (Git LFS) и /npm следуют спецификациям своих клиентов и используют собственные форматы ошибок. Они не входят в документ OpenAPI. См. Клиенты и протоколы.

Размеры и счётчики ​

Число JSON не может передать любое 64-битное значение. Поэтому Arkvory отправляет размеры и счётчики байтов как десятичные строки: "size": "1048576". То же относится к размеру, который вы объявляете при создании загрузки. В размере нет знака, нет ведущих нулей и не больше 16 цифр. Количества, версии, ограничения и индексы частей — обычные целые числа JSON.

Наибольший объект — 10 000 ГиБ (10 737 418 240 000 байт), если администратор не задал меньшее значение ARKVORY_MAX_OBJECT_BYTES. Заявленный размер сверх этого отклоняется с кодом 400.

Аутентификация ​

Каждая операция, кроме входа, общедоступных проверок работоспособности и параметров входа, требует учётных данных в заголовке Authorization: Bearer <ключ>. Учётные данные — это сессия консоли, персональный токен доступа, ключ сервиса или ключ восстановления. Что можно делать с учётными данными, зависит от их вида и от правила доступа каждой операции. Прочитайте страницу Аутентификация, прежде чем проектировать интеграцию, и выдайте автоматизации ключ сервиса только с теми действиями, которые ей нужны.

Обнаружение возможностей ​

Клиент может спросить сервер, что тот поддерживает, а не угадывать. Все эти запросы требуют учётных данных.

ЗапросОтвет
GET /api/v1/capabilitiesВерсии API (v1), роль шлюза (api или reader), флаги возможностей и ограничения этого сервера: maxObjectBytes, partBytes (наименьшая часть, 8 МиБ), maxPartBytes (1 ГиБ), maxParts (10 000) и maxPageSize (100).
GET /api/v1/operationsОперации, которые эти учётные данные, вероятно, могут вызывать, — каждая с operationId, методом, путём, surface, классом retry, требуемыми действиями и остальными условиями. Фильтруйте параметрами repository, surface, after и limit (от 1 до 100, по умолчанию 50). Список носит справочный характер: решает только настоящий запрос.
GET /api/v1/openapi.jsonДокумент OpenAPI 3.0.3 для API узла записи. Добавьте ?surface=<имя>, чтобы получить только одну область.
GET /api/v1/auth/permissionsДействия этих учётных данных по репозиториям.
GET /api/v1/auth/meЧьи это учётные данные, их вид и их общие права read и write.
GET /api/v1/repositoriesРепозитории, которые эти учётные данные могут видеть.

Читайте ограничения через capabilities, а не вшивайте их в код. Неизвестный флаг возможности считайте равным false.

Области ​

Операции сгруппированы в шесть областей (surface). Это метки контракта, а не отдельные службы; URL не меняются.

ОбластьЧто охватывает
discoveryВозможности, каталог операций, OpenAPI и репозитории
identityВход, сведения о самом вызывающем, токены и активация ключей
catalogАртефакты, описания, пакеты, файлы по пути, стадии, продвижение, вложения
transfersСессии загрузки, части, задания завершения и скачивания
administrationУчётные записи, группы, сервисные учётные записи, ключи, делегирование, обновления и резервные копии
operationsПроверка живости, готовность, метрики и обратная связь

Проверки работоспособности — это GET /health/live (процесс работает) и GET /health/status (общедоступный; {"status":"ready"} или unavailable) без учётных данных, а также GET /health/ready и GET /health/metrics с ними. Они не расходуют бюджет запросов, поэтому нагрузка не заставит балансировщик убрать сервер.

Постраничный вывод ​

Список возвращается по страницам. В ответе есть items и next. Когда next не равен null, отправьте его без изменений в параметре запроса after, чтобы прочитать следующую страницу; когда он равен null, список закончился. Считайте курсор непрозрачной строкой и не составляйте его сами.

limit задаёт размер страницы от 1 до 100. Большинство списков возвращает 50 элементов, если параметр не указан. Страницы — это не снимок: элементы, которые появляются, пока вы читаете, могут попасть в список, а могут и не попасть. Фильтры и порядок сортировки должны оставаться прежними, пока вы идёте по next.

Версии и compare-and-swap ​

У того, что редактируют люди, есть версия, которая растёт с 1: метки, метаданные и коллекции артефакта, вложения сборки, путь файла, политика хранения, план резервного копирования и настройки сервисной учётной записи. Изменение указывает ожидаемую версию в теле запроса, в поле expectedRevision:

json
{ "expectedRevision": 3, "value": { "labels": ["tested"], "metadata": {}, "collections": [] } }

Если текущая версия не равна 3, ничего не меняется, и сервер отвечает 409 с причиной revision_mismatch. Это compare-and-swap (сравнение и замена). Прочитайте состояние заново, примените к нему своё изменение и отправьте новую версию. Никогда не повторяйте запрос в цикле со всё большим числом, чтобы продавить запись. Для того, чего ещё нет, например нового пути, укажите 0. API не использует заголовок If-Match.

У скачиваемого артефакта другое проверочное значение — ETag. См. Скачивание по диапазонам и ETag.

Ключи идемпотентности ​

Заголовок Idempotency-Key делает так, что повторный запрос срабатывает один раз. Используйте значение из 1–128 символов: буквы, цифры и _ . : -, и сохраняйте его вместе с состоянием задания до первого запроса, чтобы перезапущенное задание повторяло тот же ключ. Такие операции записи требуют ключа:

ОперацияПовтор с тем же ключом и тем же телом
createUploadВозвращает ту же сессию загрузки.
issueServiceKey и rotateServiceKeyВозвращает метаданные ключа с кодом 200, без секрета. Если вы потеряли секрет, отзовите ключ и выпустите другой.
requestBackupRun, requestBackupVerify, requestBackupRetentionВозвращает тот же запрос вместо постановки в очередь ещё одного.

Тот же ключ с другим телом отклоняется с кодом 409 и причиной idempotency_mismatch. Ключ привязан к вызывающему и к цели, поэтому два вызывающих могут использовать одно значение.

Другие операции записи безопасно повторять по другой причине: они задают состояние (установка стадии, регистрация пакета, отзыв ключа) или являются compare-and-swap. Какие именно — сказано в следующем разделе.

Правила повтора ​

У каждой операции есть класс повтора. Класс подсказывает клиенту, что делать, если он не получил ответ. В справочнике он показан у каждой операции в строке «Повтор».

КлассЗначениеЧто делать
readЧтение ничего не меняет.Повторяйте с задержкой (backoff).
idempotentТот же запрос даёт тот же эффект.Повторяйте. Ответ может отличаться в деталях: повторное удаление может сообщить, что объекта уже нет.
idempotency-keyБезопасно только с ключом.Повторяйте с тем же Idempotency-Key и тем же телом.
compare-and-swapИзменение, которое зависит от версии.Прочитайте состояние, примите решение заново и повторите с прочитанной версией. Никогда не увеличивайте expectedRevision, чтобы пройти 409.
reconcile-uploadШаг сессии загрузки.Сначала прочитайте загрузку и её части (getUpload, listUploadParts), затем отправьте недостающее. PUT целого файла не может продолжиться с середины: он начинается заново с нулевого байта.
reconcile-jobПостановка задания завершения в очередь.Сначала прочитайте задание (getCompletionJob). Задание, завершившееся ошибкой, можно поставить в очередь снова.
never-automaticПовтор может выполнить действие дважды.Не повторяйте автоматически. Проверьте результат, затем решайте. Примеры: создание учётной записи, токена или ссылки на скачивание, запуск политики хранения, отправка обратной связи.

Сетевой сбой и статусы 408, 429, 502, 503 и 504 временные: повторяйте по правилам класса, ждите не меньше, чем указано в Retry-After, и добавляйте экспоненциальную задержку с ограничением числа попыток. Не повторяйте 401, 403 и другие ответы 4xx, не изменив запрос. Не повторяйте 500 вслепую; сообщите ID запроса в поддержку. После 503 на изменение результат неизвестен, поэтому выясните по классу, что произошло. SDK и клиент командной строки применяют эти правила.

Скачивание по диапазонам и ETag ​

GET и HEAD для …/artifacts/{id}/content возвращают исходные байты со строгим ETag вида "sha256:<hex>" и Accept-Ranges: bytes. То же относится к скачиванию по пакету (…/packages/content) и по пути файла (…/asset/content, …/raw/{path}). Они при каждом запросе заново ищут текущий артефакт; packages/content и raw называют выбранный артефакт в X-Arkvory-Artifact-Id, поэтому его можно закрепить для продолжения скачивания.

  • Range: bytes=0-1023, bytes=1024- и bytes=-1024 возвращают 206 с Content-Range. Сервер отдаёт один диапазон; на список диапазонов он отвечает всем файлом.
  • Начало за концом файла возвращает 416 с кодом invalid_input, причиной range_not_satisfiable и Content-Range: bytes */<размер>.
  • Чтобы продолжить скачивание, отправьте Range вместе с If-Range: "<ETag, который вы видели>". Если содержимое под этим именем изменилось, ETag будет другим, и вы получите целиком новый файл, а не смесь старого с новым.
  • If-None-Match с ETag возвращает 304 без тела.
  • Проверяйте SHA-256 того, что сохранили. ETag его содержит.

Ссылка на скачивание (?token=) работает на маршруте содержимого одного артефакта. См. Аутентификация.

Ошибки ​

У каждого сбоя один и тот же JSON-конверт: code, message, requestId и, если есть что добавить, reason, details и retryAfterSeconds. Решайте по code и reason, никогда по message. Неизвестные причины считайте отсутствующими, а неизвестный code обрабатывайте по его HTTP-статусу. См. Ошибки.

Лимиты и занятость сервера ​

Arkvory не считает вызовы API в минуту. Он ограничивает, сколько работы выполняет одновременно, и ограничивает попытки подобрать пароль:

  • Занятость. Сервер допускает фиксированное число одновременных запросов и передач (ARKVORY_MAX_REQUESTS, по умолчанию 128; по умолчанию 2 загрузки и 16 скачиваний). Передача может ждать в ограниченной очереди до 20 секунд. Если места нет, ответ — 503 с кодом busy. Повторите после Retry-After.
  • Ёмкость. Исчерпанный резерв диска, квота или предел числа объектов возвращает 507; ожидание это не исправит.
  • Попытки. Слишком много попыток входа, регистрации, смены пароля или отправки обратной связи возвращает 429 с кодом rate_limited. См. Аутентификация.

И 429, и 503 несут заголовок Retry-After в секундах (2, если у сервера нет оценки) и то же число в retryAfterSeconds. Если запрос идёт через прокси-сервер, прокси может добавить собственные ограничения.

ID запросов ​

В каждом ответе есть заголовок X-Request-Id, а в каждой ошибке то же значение лежит в requestId. Записывайте его в журнал своего задания и называйте в поддержке. ID запроса, который вы отправляете, используется, только если он приходит через прокси-сервер из ARKVORY_TRUSTED_PROXIES и состоит из 8–128 безопасных символов; иначе сервер создаёт новый. Заголовок W3C traceparent записывается только в журнал доступа сервера.

Браузеры и CORS ​

Веб-страница на том же адресе, что и Arkvory, работает без настроек. Страница на другом адресе работает, только если администратор перечислил её точный источник (origin) в ARKVORY_CORS_ORIGINS (до 16, HTTPS или HTTP на loopback). Другой источник получает 403 с причиной origin_not_allowed, даже если ключ действителен. Запросы никогда не используют cookie: отправляйте ключ в заголовке Authorization и держите его в памяти. См. Переменные окружения.

Обещание совместимости ​

/api/v1 меняется только добавлением: новые операции, новые необязательные поля запроса, новые поля ответа, новые причины ошибок и новые флаги возможностей. Изменение, которое сломало бы клиент, — другой смысл, новое обязательное поле, другой статус или другая постраничность, — получает новую версию API и период, в течение которого работают обе. Взамен ваш клиент должен:

  • игнорировать поля ответа, которых не знает;
  • считать неизвестную reason отсутствующей, а неизвестный code обрабатывать по HTTP-статусу;
  • брать ограничения из capabilities;
  • отправлять только те поля, которые определяет операция.

Значения operationId — стабильные имена. Используйте их, когда сопоставляете операции со своим кодом.

Пример: загрузить один файл и скачать его ​

Эта последовательность загружает файл одним запросом. Для файлов больше нескольких гигабайт или для ненадёжных каналов используйте arkvoryctl или SDK: они отправляют части и продолжают после сбоя. В примере для чтения JSON используется jq.

Сначала задайте адрес и ключ и вычислите размер и SHA-256 файла:

bash
export ARKVORY_URL=https://arkvory.example
export ARKVORY_KEY="$(cat ~/.arkvory/key)"
FILE=./Setup.exe
SIZE=$(stat -c %s "$FILE")
SHA=$(sha256sum "$FILE" | cut -d ' ' -f 1)

Шаг 1. Зарезервируйте загрузку. Тот же Idempotency-Key возвращает ту же сессию, поэтому этот вызов можно безопасно повторять.

bash
ID=$(curl -fsS -X POST "$ARKVORY_URL/api/v1/repositories/releases/uploads" \
  -H "Authorization: Bearer $ARKVORY_KEY" \
  -H "Idempotency-Key: build-1042-setup" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"Setup.exe\",\"size\":\"$SIZE\",\"sha256\":\"$SHA\",\"labels\":[\"nightly\"]}" \
  | jq -r .id)

Шаг 2. Отправьте байты. Сервер публикует артефакт, когда размер и SHA-256 совпадают.

bash
curl -fsS -X PUT "$ARKVORY_URL/api/v1/repositories/releases/uploads/$ID/content" \
  -H "Authorization: Bearer $ARKVORY_KEY" \
  -H "Content-Type: application/octet-stream" \
  -T "$FILE" | jq '{id, status}'

Шаг 3. Скачайте файл. ID артефакта совпадает с ID загрузки.

bash
curl -fL -o Setup-copy.exe \
  -H "Authorization: Bearer $ARKVORY_KEY" \
  "$ARKVORY_URL/api/v1/repositories/releases/artifacts/$ID/content"
sha256sum Setup-copy.exe

Шаг 2 отвечает {"id": "…", "status": "available"}. Если соединение оборвалось во время шага 2, прочитайте загрузку запросом GET …/uploads/$ID: пока её статус pending, отправьте файл снова с начала. Сессия загрузки существует 7 дней. Ключу нужны действия upload.create, upload.write, upload.complete и content.read в releases. См. Загрузки и Передачи.

Справочные страницы ​

На каждой странице перечислены операции одной группы с правилом доступа, классом повтора, параметрами и ответами.

Связанные страницы: Аутентификация, Ошибки, TypeScript SDK.

Arkvory · ProAnimaStudio