feat: add api for manage bucket

This commit is contained in:
2026-08-21 12:24:59 +07:00
parent 4d0856eb76
commit c4873840d4
12 changed files with 1808 additions and 345 deletions
+2 -2
View File
@@ -24,11 +24,11 @@ Bucket `?acl`, `?versioning`, and `?location` requests are currently treated as
## Directories and objects
Directories are physical Google Drive folders created from object-key path segments. The Worker does not create zero-byte directory marker objects. An empty prefix can therefore exist as a Drive folder without an S3 marker object.
Directories are physical Google Drive folders created from object-key path segments. The Worker does not create zero-byte directory marker objects. An empty prefix can therefore exist as a Drive folder without an S3 marker object. Folder deletion via `/api/objects/folder` refuses non-empty folders by default, and supports atomic recursive deletion into Google Drive trash when `recursive=1` is provided (avoiding partial deletion via enumeration).
## Multipart behavior
Parts must be uploaded strictly in consecutive order beginning at part 1. Parts are immutable after they have committed. An incomplete upload expires after 24 hours. `ETAG_STYLE=md5` returns Google Drive's file MD5 for completed multipart objects; `ETAG_STYLE=multipart` is available only for clients that require an S3-style composite ETag.
Parts must be uploaded strictly in consecutive order beginning at part 1. Parts are immutable after they have committed. Default part size recommended and returned by the API is 8 MiB (aligned to Google Drive 256 KiB chunks). An incomplete upload expires after 24 hours. `ETAG_STYLE=md5` returns Google Drive's file MD5 for completed multipart objects; `ETAG_STYLE=multipart` is available only for clients that require an S3-style composite ETag.
## Quotas and plan limits
+377
View File
@@ -301,6 +301,383 @@ paths:
content:
application/json:
schema: { $ref: '#/components/schemas/AuthError' }
/api/objects:
get:
tags: [Objects API]
operationId: listObjectsApi
summary: List objects and folders in a bucket (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: prefix
schema: { type: string, default: "" }
- in: query
name: delimiter
schema: { type: string, default: "/" }
responses:
'200':
description: Object and folder listing.
content:
application/json:
schema:
type: object
properties:
bucket: { type: string }
prefix: { type: string }
delimiter: { type: string, nullable: true }
folders:
type: array
items:
type: object
properties:
prefix: { type: string }
name: { type: string }
objects:
type: array
items:
type: object
properties:
key: { type: string }
name: { type: string }
size: { type: integer }
contentType: { type: string }
lastModified: { type: string, nullable: true }
etag: { type: string }
truncated: { type: boolean }
'400':
description: Missing query parameters.
'401':
description: Unauthorized.
'404':
description: Bucket not found.
delete:
tags: [Objects API]
operationId: deleteObjectApi
summary: Delete an object (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'204':
description: Object deleted.
'401':
description: Unauthorized.
'404':
description: Bucket or object not found.
/api/objects/metadata:
get:
tags: [Objects API]
operationId: getObjectMetadataApi
summary: Get object metadata (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'200':
description: Object metadata.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
name: { type: string }
size: { type: integer }
contentType: { type: string }
lastModified: { type: string, nullable: true }
etag: { type: string }
'404':
description: Object not found.
/api/objects/content:
get:
tags: [Objects API]
operationId: getObjectContentApi
summary: Download object content (Dashboard Session Auth or Ticket)
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: ticket
schema: { type: string }
responses:
'200':
description: Binary object data.
'206':
description: Partial content.
'404':
description: Object not found.
put:
tags: [Objects API]
operationId: putObjectContentApi
summary: Direct single-part upload (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
responses:
'200':
description: Object uploaded.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
etag: { type: string }
size: { type: integer }
/api/objects/folder:
post:
tags: [Objects API]
operationId: createFolderApi
summary: Create a folder (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, prefix]
properties:
bucket: { type: string }
prefix: { type: string }
responses:
'201':
description: Folder created.
'409':
description: Folder already exists.
delete:
tags: [Objects API]
operationId: deleteFolderApi
summary: Delete a folder (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: prefix
required: true
schema: { type: string }
- in: query
name: recursive
schema: { type: string, enum: ["0", "1"] }
responses:
'204':
description: Folder deleted.
'409':
description: Folder is not empty.
/api/objects/download-ticket:
post:
tags: [Objects API]
operationId: createDownloadTicket
summary: Create a temporary single-use download ticket (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key]
properties:
bucket: { type: string }
key: { type: string }
responses:
'201':
description: Download ticket created.
content:
application/json:
schema:
type: object
properties:
ticket: { type: string }
downloadUrl: { type: string }
expiresIn: { type: integer }
/api/objects/uploads:
post:
tags: [Objects API]
operationId: initiateMultipartApi
summary: Initiate a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key]
properties:
bucket: { type: string }
key: { type: string }
contentType: { type: string }
responses:
'201':
description: Upload initiated.
content:
application/json:
schema:
type: object
properties:
uploadId: { type: string }
bucket: { type: string }
key: { type: string }
partSize: { type: integer }
delete:
tags: [Objects API]
operationId: abortMultipartApi
summary: Abort a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
responses:
'204':
description: Upload aborted.
/api/objects/uploads/part:
put:
tags: [Objects API]
operationId: uploadPartApi
summary: Upload a part (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
- in: query
name: partNumber
required: true
schema: { type: integer }
responses:
'200':
description: Part uploaded.
content:
application/json:
schema:
type: object
properties:
partNumber: { type: integer }
etag: { type: string }
/api/objects/uploads/complete:
post:
tags: [Objects API]
operationId: completeMultipartApi
summary: Complete a multipart upload (Dashboard Session Auth)
security:
- sessionBearer: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [bucket, key, uploadId, parts]
properties:
bucket: { type: string }
key: { type: string }
uploadId: { type: string }
parts:
type: array
items:
type: object
required: [partNumber, etag]
properties:
partNumber: { type: integer }
etag: { type: string }
totalSize: { type: integer }
responses:
'200':
description: Upload completed.
content:
application/json:
schema:
type: object
properties:
key: { type: string }
etag: { type: string }
/api/objects/uploads/parts:
get:
tags: [Objects API]
operationId: listPartsApi
summary: List uploaded parts (Dashboard Session Auth)
security:
- sessionBearer: []
parameters:
- in: query
name: bucket
required: true
schema: { type: string }
- in: query
name: key
required: true
schema: { type: string }
- in: query
name: uploadId
required: true
schema: { type: string }
responses:
'200':
description: Parts list.
/{bucket}:
parameters:
- $ref: '#/components/parameters/Bucket'