파일 저장소
storage 카테고리의 API 작업 8개를 다룹니다.
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/storage | 객체 스토리지 상태 (runlot storage usage) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/storage | 끈 저장소를 다시 켭니다 |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/storage | 프로젝트 Storage 제거(runlot storage delete) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/storage/public | 게시된 키 접두사입니다 (runlot storage public list) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/storage/public | 키 접두사를 게시합니다 (runlot storage public add) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/storage/public | 키 접두사 게시를 취소합니다 (runlot storage public rm) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/storage/objects | 오브젝트 목록 조회(runlot storage ls) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/storage/objects/{key} | 오브젝트 하나에 대한 단기 서명 URL(runlot storage download) |
GET /v1/orgs/{orgSlug}/projects/{projectName}/storage
오브젝트 스토리지 활성화 여부와 프리픽스, 할당량, 사용량입니다. usedBytes는 마지막으로 보고된 값이므로 보고 주기만큼 지연되며, 그 사이에 할당량을 약간 초과할 수 있습니다.
오브젝트 목록 조회와 서명된 URL은 이 API에 포함되지 않습니다. 워커에서 env.storage를 사용하세요.
viewer 이상이 필요합니다.
operationId getStorage
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 스토리지 상태 | StorageStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/storage
이 작업은 멱등적입니다 — 두 번 호출해도 프리픽스는 변경되지 않으므로, 재시도해도 오브젝트가 보이지 않게 되는 일은 없습니다.
요청 본문이 없습니다. 프리픽스는 프로젝트별로 고정되고 할당량은 플랜에 의해 설정되므로, 둘 다 직접 설정하는 값이 아닙니다.
활성화하면 잠시 후 env.storage가 워커에 연결됩니다. env.db와 마찬가지로 재배포가 필요하지 않습니다.
member 이상의 권한이 필요합니다. storage.grant로 감사 기록됩니다.
operationId grantStorage
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 부여 상태(이미 있었다면 기존 값) | StorageStatus |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/storage
오브젝트는 삭제되지 않습니다. 스토리지를 끄면 프로젝트에서 분리되며 감사 로그에 기록되지만, 저장된 오브젝트는 그대로 남습니다.
비활성화 역시 idempotent합니다. 스토리지가 활성화되어 있지 않았을 때도 204를 반환합니다.
admin 이상의 권한이 필요합니다 — 청구는 중단되지만 오브젝트는 남아 있습니다. storage.revoke로 감사 기록됩니다.
operationId revokeStorage
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 204 | 분리됨 | — |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/storage/public
이 프로젝트가 https://objects.runlot.io/<org>/<project>/<key>에서 서명 없이 제공하는 키 프리픽스입니다.
저장된 프리픽스는 정규화됩니다. assets는 assets/가 되고, /는 빈 문자열이 되어 프로젝트 스토리지의 모든 키를 의미하게 됩니다. 매칭은 단순 문자열 프리픽스 검사이므로, 끝의 슬래시가 있어야 assets가 assets-private/까지 함께 열리는 것을 막을 수 있습니다.
viewer 이상이 필요합니다.
operationId listStoragePublic
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 목록 | StoragePublicList |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/storage/public
이 프리픽스 아래의 모든 키를 서명 없이 HTTPS를 통해 누구나 읽을 수 있게 만듭니다. 버킷 자체는 비공개로 유지됩니다. 오브젝트를 읽기 전에 모든 요청이 이 목록과 대조됩니다.
멱등적이며, 변경 후 전체 목록으로 응답합니다.
프로젝트당 최대 20개의 프리픽스입니다.
admin 이상의 권한이 필요합니다. 공개하면 프로젝트의 바이트가 인터넷에서 읽을 수 있게 됩니다. storage.public.add로 감사 기록되며, 정규화로 인해 둘이 달라질 수 있으므로 전송된 값과 저장된 값을 모두 기록합니다.
operationId addStoragePublic
요청 본문: application/json · StoragePublicRequest
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 변경 후 목록 | StoragePublicList |
| 400 | 프리픽스가 비어 있거나, 정규화할 수 없거나, 프로젝트의 슬라이스를 벗어나게 됩니다 | Error |
| 403 | — | — |
| 404 | — | — |
| 409 | storage_not_granted 또는 too_many_public_prefixes | Error |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/storage/public
프리픽스에 슬래시가 포함될 수 있으므로, 경로가 아닌 요청 본문으로 전달됩니다.
멱등적입니다 — 존재하지 않는 항목을 제거해도 변경되지 않은 목록과 함께 200이 반환됩니다.
외부에서는 최대 60초 동안 계속 읽을 수 있습니다. 공개된 목록은 해당 TTL로 캐시되므로, 이 호출은 반환 즉시 효력이 발생하는 취소가 아닙니다.
admin 이상의 권한이 필요합니다. storage.public.remove로 감사 기록됩니다.
operationId removeStoragePublic
요청 본문: application/json · StoragePublicRequest
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 변경 후 목록 | StoragePublicList |
| 400 | 프리픽스가 비어 있거나 정규화할 수 없습니다 | Error |
| 403 | — | — |
| 404 | — | — |
| 503 | no_core — 서비스를 일시적으로 사용할 수 없습니다 | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/storage/objects
프로젝트 오브젝트의 한 페이지이며, 파일 브라우저처럼 / 기준으로 그룹화됩니다. entries는 prefix 바로 아래의 오브젝트이고, prefixes는 한 단계 아래의 디렉터리입니다.
키는 worker가 쓰는 그대로의 키(env.storage.put(key, …))이며, 내부 p/<projectId>/ 접두어는 포함하지 않습니다. 이 접두어는 격리 경계이지 주소의 일부가 아닙니다.
키가 이 프로젝트가 공개한 접두어(…/storage/public) 아래에 있으면 public이 true이고, 이때 url은 누구나 읽을 수 있는 서명 없는 주소입니다. 비공개 오브젝트에는 url이 없습니다. 이 필드는 "누구나 읽을 수 있다"는 뜻이므로, 여기에 서명된 URL을 넣으면 비공개 오브젝트가 공개된 것처럼 보이기 때문입니다. 비공개 오브젝트는 …/storage/objects/{key}에 요청하세요.
페이지 이동은 cursor로 하며, 경계는 그룹 사이에 놓입니다. 어떤 디렉터리도 두 번 나오거나 누락되지 않습니다. cursor를 변경하지 말고 그대로 다시 전달하세요. 없으면 마지막 페이지입니다.
viewer 이상이 필요합니다.
operationId listStorageObjects
| 매개변수 | 위치 | 필수 | 타입 | 설명 |
|---|---|---|---|---|
prefix | query | 아니오 | 문자열 | 목록을 조회할 키 접두어입니다. 공개 접두어와 같은 방식으로 정규화됩니다. assets는 assets/가 되고, 비어 있으면 프로젝트 루트를 뜻합니다. |
cursor | query | 아니오 | 문자열 | 이전 페이지의 cursor |
limit | query | 아니오 | 정수 | 한 페이지의 entries와 prefixes |
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 한 페이지 | StorageObjectPage |
| 400 | prefix를 정규화할 수 없거나 limit이 범위를 벗어났습니다 | Error |
| 403 | — | — |
| 404 | — | — |
| 409 | storage_not_granted — 이 프로젝트에는 파일 스토리지가 없습니다 | Error |
| 502 | objects_unreachable — 오브젝트 스토어가 응답하지 않았습니다 | Error |
| 503 | objects_unavailable — 이 설치에는 오브젝트 스토어가 없습니다. 또는 no_core | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/storage/objects/{key}
5분 동안 유효한 GET URL이며, 브라우저나 CLI가 오브젝트 프런트에서 직접 가져옵니다. 바이트는 이 API를 거치지 않습니다.
서명하기 전에 오브젝트를 먼저 조회하므로, 아무것도 없는 키는 몇 분 뒤 연관 지을 수 없는 곳에서 404가 나는 URL이 아니라 여기서 바로 404를 반환합니다.
GET만 서명됩니다. 업로드와 삭제는 이 화면에 없으며, worker에서 env.storage를 통해 쓰세요.
viewer 이상이 필요합니다.
operationId signStorageObject
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 서명된 URL과 오브젝트의 메타데이터 | StorageObjectSigned |
| 400 | 키가 비어 있거나, 프로젝트 접두어를 벗어나거나, 1024바이트를 초과합니다 | Error |
| 403 | — | — |
| 404 | — | — |
| 409 | storage_not_granted — 이 프로젝트에는 파일 스토리지가 없습니다 | Error |
| 503 | objects_unavailable — 이 설치에는 오브젝트 스토어가 없습니다. 또는 no_core | Error |