Обзор 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:
{ "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 файла:
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 возвращает ту же сессию, поэтому этот вызов можно безопасно повторять.
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 совпадают.
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 загрузки.
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. См. Загрузки и Передачи.
Справочные страницы
На каждой странице перечислены операции одной группы с правилом доступа, классом повтора, параметрами и ответами.
- Система и состояние: живость, готовность, метрики, OpenAPI, возможности
- Репозитории
- Загрузки
- Артефакты и каталог
- Пакеты
- Файлы по пути
- Стадии и продвижение
- Политики хранения
- Зеркала
- Ссылки на скачивание
- Вложения сборки
- Учётные записи и вход
- Сервисные аккаунты и ключи
- Резервные копии
- Обновления
- Обратная связь
Связанные страницы: Аутентификация, Ошибки, TypeScript SDK.