S3 Storage Support
GQLForge can integrate with Amazon S3 and S3-compatible storage services (MinIO, Cloudflare R2, etc.) using the @s3 directive. This enables presigned URL generation, object listing, and deletion directly from your GraphQL API.
Connecting to S3
Register an S3 endpoint with @link using the S3 link type:
schema
@server(port: 8000)
@link(id: "aws", type: S3, src: "https://s3.ap-northeast-1.amazonaws.com", meta: { region: "ap-northeast-1" }) {
query: Query
mutation: Mutation
}
Connection Parameters
The @link directive for S3 accepts the following:
| Parameter | Location | Description |
|---|---|---|
id | @link | Identifier to reference this connection in @s3(linkId: ...). |
src | @link | The S3 endpoint URL. Optional for AWS S3 (the SDK resolves the endpoint from the region). Required for S3-compatible services. |
meta.region | @link | AWS region (default: us-east-1). |
meta.forcePathStyle | @link | Use path-style addressing (default: false). Required for MinIO. |
AWS Credentials
Credentials are resolved via the standard AWS credential chain:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - Shared credentials file (
~/.aws/credentials) - IAM instance profile (EC2, ECS, Lambda)
- Web identity token (EKS)
No credentials are stored in the GraphQL schema.
S3-Compatible Services
MinIO
schema @link(id: "minio", type: S3, src: "http://localhost:9000", meta: { region: "us-east-1", forcePathStyle: true }) {
query: Query
}
Cloudflare R2
schema @link(id: "r2", type: S3, src: "https://<ACCOUNT_ID>.r2.cloudflarestorage.com", meta: { region: "auto" }) {
query: Query
}
Multiple S3 Connections
You can define multiple S3 connections and select them with the linkId field:
schema
@link(id: "aws", type: S3, src: "https://s3.ap-northeast-1.amazonaws.com", meta: { region: "ap-northeast-1" })
@link(id: "minio", type: S3, src: "http://localhost:9000", meta: { region: "us-east-1", forcePathStyle: true }) {
query: Query
mutation: Mutation
}
type Query {
awsFile(key: String!): String!
@s3(bucket: "prod-bucket", operation: GET_PRESIGNED_URL, key: "{{.args.key}}", linkId: "aws")
localFile(key: String!): String!
@s3(bucket: "dev-bucket", operation: GET_PRESIGNED_URL, key: "{{.args.key}}", linkId: "minio")
}
The @s3 Directive
Use @s3 on fields to map them to S3 operations:
type Query {
getFileUrl(key: String!): String!
@s3(bucket: "my-bucket", operation: GET_PRESIGNED_URL, key: "{{.args.key}}", expiration: 3600)
listFiles(prefix: String): JSON! @s3(bucket: "my-bucket", operation: LIST, prefix: "{{.args.prefix}}")
}
type Mutation {
uploadUrl(key: String!, contentType: String): String!
@s3(bucket: "my-bucket", operation: PUT_PRESIGNED_URL, key: "{{.args.key}}", contentType: "{{.args.contentType}}")
deleteFile(key: String!): Boolean! @s3(bucket: "my-bucket", operation: DELETE, key: "{{.args.key}}")
}
See @s3 Directive for the full field reference.
Enabling S3 Support
S3 support requires the s3 feature flag:
cargo build --features s3
This pulls in aws-sdk-s3 and aws-config as dependencies.