Wie man vorab signierte URLs für Amazon S3 mit Astro auf Cloudflare Workers generiert
LaunchFast Logo LaunchFast

Wie man vorab signierte URLs für Amazon S3 mit Astro auf Cloudflare Workers generiert

Rishi Raj Jain
How to Generate Pre-signed URLs for Amazon S3 with Cloudflare Workers

In diesem Leitfaden erfahren Sie, wie Sie vorab signierte URLs für Amazon S3 mit Astro auf Cloudflare Workers generieren. Sie durchlaufen den Prozess der Einrichtung eines neuen Astro-Projekts, der Aktivierung der serverseitigen Rendering mit dem Cloudflare-Adapter, der Beschaffung von AWS-Anmeldeinformationen und dann der Erstellung von Funktionen zur Generierung vorab signierter URLs für den Abruf und das Hochladen von Amazon S3.

Hochwertige Starter-Kits mit integriertem Authentifizierungsfluss (Auth.js), Objekt-Uploads (AWS, Clouflare R2, Firebase Storage, Supabase Storage), integrierten Zahlungen (Stripe, LemonSqueezy), E-Mail-Verifizierungsablauf (Resend, Postmark, Sendgrid) und viel mehr . Kompatibel mit jeder Datenbank (Redis, Postgres, MongoDB, SQLite, Firestore).

Voraussetzungen

Um folgen zu können, benötigen Sie:

Inhaltsverzeichnis

Erstellen einer neuen Astro-Anwendung

Lassen Sie uns beginnen, indem wir ein neues Astro-Projekt erstellen. Öffnen Sie Ihr Terminal und führen Sie den folgenden Befehl aus:

Terminal window
npm create astro@latest my-app

npm create astro ist der empfohlene Weg, um schnell ein Astro-Projekt zu erstellen.

Wenn Sie dazu aufgefordert werden, wählen Sie:

  • Use minimal (empty) template, wenn Sie gefragt werden, wie Sie das neue Projekt starten möchten.
  • Yes, wenn Sie gefragt werden, ob Abhängigkeiten installiert werden sollen.
  • Yes, wenn Sie gefragt werden, ob ein Git-Repository initialisiert werden soll.

Sobald dies erledigt ist, können Sie in das Projektverzeichnis wechseln und die App starten:

Terminal window
cd my-app
npm run dev

Die App sollte auf localhost:4321 laufen. Führen Sie als Nächstes den folgenden Befehl aus, um die notwendige Bibliothek für den Aufbau der Anwendung zu installieren:

Terminal window
npm install aws4fetch

Die folgende Bibliothek wird installiert:

  • aws4fetch: Ein AWS-Client für Umgebungen, die Fetch und SubtleCrypto unterstützen.

Integration des Cloudflare-Adapters in Ihr Astro-Projekt

Um vorab signierte URLs für jedes Objekt dynamisch zu generieren, aktivieren Sie das serverseitige Rendering in Ihrem Astro-Projekt über den Cloudflare-Adapter. Führen Sie den folgenden Befehl aus:

Terminal window
npx astro add cloudflare

Wenn Sie dazu aufgefordert werden, wählen Sie Folgendes:

  • Y, wenn Sie gefragt werden, ob die Cloudflare-Abhängigkeiten installiert werden sollen.
  • Y, wenn Sie gefragt werden, ob Änderungen an der Astro-Konfigurationsdatei vorgenommen werden sollen.

Sie haben das serverseitige Rendering in Astro erfolgreich aktiviert.

Um sicherzustellen, dass die Ausgabe auf Cloudflare Workers bereitgestellt werden kann, erstellen Sie eine wrangler.toml-Datei im Stammverzeichnis des Projekts mit dem folgenden Code:

wrangler.toml
name = "amazon-s3-astro-workers"
main = "dist/_worker.js"
compatibility_date = "2025-04-01"
compatibility_flags = [ "nodejs_compat" ]
[assets]
directory="dist"
binding="ASSETS"
[vars]
AWS_KEY_ID=""
AWS_REGION_NAME=""
AWS_S3_BUCKET_NAME=""
AWS_SECRET_ACCESS_KEY=""

Stellen Sie danach sicher, dass Sie sowohl eine .env-Datei als auch eine wrangler.toml-Datei mit den definierten Variablen haben, damit sie während npm run dev und bei der Bereitstellung auf Cloudflare Workers entsprechend zugänglich sind.

Aktualisieren Sie außerdem die astro.config.mjs-Datei mit dem Folgenden, um diese Variablen im Code programmatisch zugänglich zu machen:

astro.config.mjs
// ... Bestehende Importe...
import { defineConfig, envField } from 'astro/config'
export default defineConfig({
env: {
schema: {
AWS_KEY_ID: envField.string({ context: 'server', access: 'secret', optional: false }),
AWS_REGION_NAME: envField.string({ context: 'server', access: 'secret', optional: false }),
AWS_S3_BUCKET_NAME: envField.string({ context: 'server', access: 'secret', optional: false }),
AWS_SECRET_ACCESS_KEY: envField.string({ context: 'server', access: 'secret', optional: false }),
}
}
// adapter
})

Erstellen von Zugriffsschlüsseln für IAM-Benutzer

  • Wählen Sie in der Navigationsleiste oben rechts in Ihrem AWS-Konto Ihren Benutzernamen aus und wählen Sie dann Sicherheitsanmeldeinformationen.
Grab Deployment URL in AWS Amplify
  • Scrollen Sie nach unten zu Zugriffsschlüssel und klicken Sie auf Zugriffsschlüssel erstellen.
Grab Deployment URL in AWS Amplify
  • Klicken Sie erneut auf Zugriffsschlüssel erstellen.
Grab Deployment URL in AWS Amplify
  • Kopieren Sie den Zugriffsschlüssel und den Geheimen Zugriffsschlüssel, die als AWS_ACCESS_KEY_ID bzw. AWS_ACCESS_KEY_SECRET verwendet werden sollen.
Grab Deployment URL in AWS Amplify

Konfigurieren der Amazon S3-Bucket-Richtlinie

Um den Zugriff auf einen Amazon S3-Bucket sicher zu teilen, müssen wir eine Bucket-Richtlinie konfigurieren, die explizit definiert, wer auf den Bucket zugreifen kann und welche Aktionen er ausführen darf. In diesem Fall möchten wir einem bestimmten AWS-Konto die Berechtigung erteilen, Dateien in einem bestimmten S3-Bucket sowohl hochzuladen (PutObject) als auch herunterzuladen (GetObject). Dies ist nützlich, wenn Sie möchten, dass ein anderes Konto - wie ein Partner, eine separate Umgebung oder eine Drittanbieterintegration - programmgesteuert mit Ihrem Bucket interagiert, ohne die Inhalte öffentlich zu machen.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AuthenticatedReadUploadObjects",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<user-id>:root"
},
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::<bucket-name>/*"
}
]
}

In der obigen Konfiguration haben Sie die Get- und Put-Operationen auf den Benutzer mit der ID <user-id> und für den Bucket <bucket-name> beschränkt.

Konfigurieren von Amazon S3 CORS

Da Sie vorab signierte URLs verwenden werden, um von der Client-Seite (Browser) auf Amazon S3 hochzuladen, ist es notwendig, Amazon S3 mitzuteilen, dass es Uploads von überall im Web akzeptieren soll.

HINWEIS: Sie können die AllowedOrigins bearbeiten, um auf bestimmte Domains zu beschränken, aber in diesem Fall sind wir weniger besorgt über das Zugriffslevel, da wir bereits IAM-Authentifizierung erzwingen, während wir die vorab signierten URLs generieren.

[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"PUT"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 9000
}
]

Generieren der vorab signierten URLs

1. Zugriff auf die Umgebungsvariablen

Der erste Schritt besteht darin, während der Laufzeit auf die notwendigen Umgebungsvariablen zuzugreifen, um einen AWS-Client über aws4fetch zu erstellen. Ab Astro 5.6 und darüber hinaus ist der Weg, wie Sie zur Laufzeit auf Umgebungsvariablen in Ihrem Code zugreifen möchten, die Verwendung der getSecret-Funktion aus astro:env/server, um die Dinge anbieterunabhängig zu halten. Dies ist entscheidend, um sensible Informationen sicher zu speichern, ohne sie in Ihre Anwendung zu hardcodieren. Sie werden die folgenden Variablen abrufen:

  • AWS-Zugriffsschlüssel-ID
  • AWS-Regionenname
  • Amazon S3-Bucket-Name
  • AWS-Geheimer Zugriffsschlüssel
src/storage/s3.ts
import { getSecret } from 'astro:env/server'
const accessKeyId = getSecret('AWS_KEY_ID')
const s3RegionName = getSecret('AWS_REGION_NAME')
const s3BucketName = getSecret('AWS_S3_BUCKET_NAME')
const secretAccessKey = getSecret('AWS_SECRET_ACCESS_KEY')

2. Definieren des AWS-Clients

Als Nächstes definieren Sie die Funktion defineAws4Fetch, die eine AWS-Client-Instanz mit den erforderlichen Umgebungsvariablen erstellt. Diese Funktion überprüft, ob die erforderlichen AWS-Anmeldeinformationen gesetzt sind, und gibt eine neue AwsClient-Instanz zurück, die für S3 konfiguriert ist.

src/storage/s3.ts
import { AwsClient } from 'aws4fetch'
// ...Bestehender Code...
async function defineAws4Fetch(): Promise<AwsClient> {
if (!accessKeyId || !secretAccessKey) {
throw new Error(`AWS_KEY_ID OR AWS_SECRET_ACCESS_KEY environment variable(s) are not set.`)
}
return new AwsClient({
service: 's3',
accessKeyId,
secretAccessKey,
region: s3RegionName,
})
}

3. Bestimmen der S3-URLs

Sie müssen eindeutige URLs für jeden Dateiupload zu Amazon S3 generieren. Die Funktion getS3URL unten kümmert sich um die Konstruktion der korrekten URL basierend auf dem Dateinamen, dem Bucket-Namen und der Region.

src/storage/s3.ts
// ...Bestehender Code...
function getS3URL({ Key }: { Key: string }) {
if (!s3BucketName) {
throw new Error(`AWS_S3_BUCKET_NAME environment variable(s) are not set.`)
}
return new URL(`/${Key}`, `https://${s3BucketName}.s3.${s3RegionName}.amazonaws.com`)
}

4. Vorab signierte URL zum Abrufen eines S3-Objekts (abrufen)

Die Funktion getS3ObjectURL unten ruft die vorab signierte URL eines Objekts von Amazon S3 ab. Sie generiert eine signierte Anfrage, die Ihnen ermöglicht, sicher auf die Datei zuzugreifen.

src/storage/s3.ts
// ...Bestehender Code...
export async function getS3ObjectURL(Key: string) {
try {
const endpointUrl = getS3URL({ Key })
endpointUrl.searchParams.set('X-Amz-Expires', '3600')
const client = await defineAws4Fetch()
const signedRequest = await client.sign(new Request(endpointUrl), { aws: { signQuery: true } })
return signedRequest.url
} catch (e: any) {
const tmp = e.message || e.toString()
console.log(tmp)
return
}
}

5. Vorab signierte URL zum Hochladen eines S3-Objekts (hochladen)

Die Funktion uploadS3ObjectURL unten ist für die Generierung einer vorab signierten URL zum Hochladen einer Datei zu Amazon S3 verantwortlich. Sie folgt einer ähnlichen Struktur wie die Funktion getS3ObjectURL und generiert eine signierte URL, die Ihnen ermöglicht, Dateien sicher hochzuladen.

src/storage/s3.ts
// ...Bestehender Code...
export async function uploadS3ObjectURL(file: { name: string; type: string }) {
try {
const Key = file.name
const endpointUrl = getS3URL({ Key })
endpointUrl.searchParams.set('X-Amz-Expires', '3600')
const client = await defineAws4Fetch()
const signedRequest = await client.sign(new Request(endpointUrl, { method: 'PUT', headers: { 'Content-Type': file.type } }), { method: 'PUT', aws: { signQuery: true } })
return signedRequest.url
} catch (e: any) {
const tmp = e.message || e.toString()
console.log(tmp)
return
}
}

6. Erstellen einer Server-Endpunkt (eine API-Route) in Astro

src/pages/api/storage.ts
import type { APIContext } from 'astro'
import { getS3ObjectURL, uploadS3ObjectURL } from '../../storage/s3'
// Definieren einer asynchronen Funktion namens GET, die ein Anforderungsobjekt akzeptiert.
export async function GET({ request }: APIContext) {
// Extrahieren des 'file'-Parameters aus der Anforderungs-URL.
const url = new URL(request.url)
const file = url.searchParams.get('file')
// Überprüfen, ob der 'file'-Parameter in der URL vorhanden ist.
if (file) {
try {
const filePublicURL = await getS3ObjectURL(file)
// Rückgabe einer Antwort mit der öffentlichen URL des Bildes und einem Statuscode von 200.
return new Response(filePublicURL)
} catch (error: any) {
// Wenn ein Fehler auftritt, protokollieren Sie die Fehlermeldung und geben Sie eine Antwort mit einem Statuscode von 500 zurück.
const message = error.message || error.toString()
console.log(message)
return new Response(message, { status: 500 })
}
}
// Wenn der 'file'-Parameter nicht in der URL gefunden wird, geben Sie eine Antwort mit einem Statuscode von 400 zurück.
return new Response('Invalid Request.', { status: 400 })
}
export async function POST({ request }: APIContext) {
// Extrahieren des 'file'-Parameters aus der Anforderungs-URL.
const url = new URL(request.url)
const type = url.searchParams.get('type')
const name = url.searchParams.get('name')
if (!type || !name) return new Response('Invalid Request.', {status:400})
try {
// Generieren einer zugänglichen URL für die hochgeladene Datei
// Verwenden Sie diese URL, um einen GET an diesen Endpunkt mit dem Dateiabfrageparameter auszuführen, der wie unten angegeben ist
const publicUploadUrl = await uploadS3ObjectURL({ type, name })
// Rückgabe einer Erfolgsantwort mit einer Nachricht
return new Response(publicUploadUrl)
} catch (error: any) {
// Wenn während des Upload-Prozesses ein Fehler aufgetreten ist, geben Sie eine 403-Antwort mit der Fehlermeldung zurück
const message = error.message || error.toString()
console.log(message)
return new Response(message, { status: 500 })
}
}

Bereitstellung für Cloudflare Workers

Um Ihre Anwendung für Cloudflare Workers bereitstellbar zu machen, erstellen Sie eine Datei namens .assetsignore im public-Verzeichnis mit folgendem Inhalt:

_routes.json
_worker.js

Als Nächstes müssen Sie das Wrangler-CLI verwenden, um Ihre Anwendung auf Cloudflare Workers bereitzustellen. Führen Sie den folgenden Befehl aus, um bereitzustellen:

Terminal window
npm run build && npx wrangler@latest deploy

Referenzen

Fazit

In diesem Blogbeitrag haben Sie gelernt, wie Sie Amazon S3 mit Astro und Cloudflare Workers für Datei-Uploads und -Abrufe integrieren. Durch das Befolgen der Implementierungsschritte können Sie Dateien sicher von Amazon S3 hochladen und abrufen und sicherstellen, dass Ihre Webanwendung eine robuste und flexible Speicherlösung hat.

Wenn Sie bestimmte Abschnitte detaillierter erkunden, bestimmte Konzepte erweitern oder zusätzliche verwandte Themen behandeln möchten, lassen Sie es mich bitte wissen, und ich helfe Ihnen gerne weiter!

Learn More Abfrage von Cloud Firestore mit Astro auf Cloudflare Workers
Abfrage von Cloud Firestore mit Astro auf Cloudflare Workers April 25, 2025
Abfrage von Redis mit Astro auf Cloudflare Workers
Abfrage von Redis mit Astro auf Cloudflare Workers April 25, 2025
Wie man vorab signierte URLs für Firebase Storage mit Astro auf Cloudflare Workers generiert
Wie man vorab signierte URLs für Firebase Storage mit Astro auf Cloudflare Workers generiert April 24, 2025