
En esta guía, aprenderás cómo generar URLs pre-firmadas para Cloudflare R2 con Astro en Cloudflare Workers. Pasarás por el proceso de configurar un nuevo proyecto Astro, habilitar la representación del lado del servidor usando el adaptador de Cloudflare, obtener credenciales de Cloudflare R2 y luego crear funciones para generar URLs pre-firmadas para la recuperación y carga desde Cloudflare R2.
Requisitos previos
Para seguir, necesitarás:
- Node.js 20 o posterior
- Una cuenta de Cloudflare
Tabla de Contenidos
- Crear una nueva aplicación Astro
- Integrar el adaptador de Cloudflare en tu proyecto Astro
- Configurar Cloudflare R2
- Generar las URLs pre-firmadas
- Desplegar en Cloudflare Workers
Crear una nueva aplicación Astro
Comencemos creando un nuevo proyecto Astro. Abre tu terminal y ejecuta el siguiente comando:
npm create astro@latest my-app
npm create astro
es la forma recomendada para crear rápidamente un proyecto Astro.
Cuando se te pida, elige:
Usar plantilla mínima (vacía)
cuando se te pregunte cómo comenzar el nuevo proyecto.Sí
cuando se te pregunte si deseas instalar dependencias.Sí
cuando se te pregunte si deseas inicializar un repositorio git.
Una vez hecho esto, puedes moverte al directorio del proyecto y comenzar la aplicación:
cd my-appnpm run dev
La aplicación debería estar ejecutándose en localhost:4321. A continuación, ejecuta el siguiente comando para instalar la biblioteca necesaria para construir la aplicación:
npm install aws4fetch
Se instala la siguiente biblioteca:
aws4fetch
: Un cliente AWS para entornos que soportan fetch y SubtleCrypto.
Integrar el adaptador de Cloudflare en tu proyecto Astro
Para generar URLs pre-firmadas para cada objeto dinámicamente, habilitarás la representación del lado del servidor en tu proyecto Astro a través del adaptador de Cloudflare. Ejecuta el siguiente comando:
npx astro add cloudflare
Cuando se te pida, elige lo siguiente:
Y
cuando se te pregunte si deseas instalar las dependencias de Cloudflare.Y
cuando se te pregunte si deseas realizar cambios en el archivo de configuración de Astro.
Has habilitado con éxito la representación del lado del servidor en Astro.
Para asegurarte de que la salida sea desplegable en Cloudflare Workers, crea un archivo wrangler.toml
en la raíz del proyecto con el siguiente código:
name = "cloudflare-r2-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_S3_BUCKET_NAME=""AWS_SECRET_ACCESS_KEY=""CLOUDFLARE_R2_ACCOUNT_ID=""
Después de eso, asegúrate de tener tanto un archivo .env
como un archivo wrangler.toml
con las variables definidas para que puedan ser accedidas durante npm run dev
y cuando se despliegue en Cloudflare Workers respectivamente.
Además, actualiza el archivo astro.config.mjs
con lo siguiente para poder acceder a estas variables en el código de manera programática:
// ... Existing imports...import { defineConfig, envField } from 'astro/config'
export default defineConfig({ env: { schema: { AWS_KEY_ID: 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 }), CLOUDFLARE_R2_ACCOUNT_ID: envField.string({ context: 'server', access: 'secret', optional: false }), } } // adapter})
Configurar Cloudflare R2
- Navega a la página de Descripción General de Cloudflare R2.

- Crea un nuevo bucket en Cloudflare R2 y guarda el nombre como
AWS_S3_BUCKET_NAME
en las variables de entorno (.env
&wrangler.toml
)

- Accede a los Detalles de la Cuenta R2 en Cloudflare R2.

- Recupera el ID de la Cuenta R2 de Cloudflare y guárdalo como
CLOUDFLARE_R2_ACCOUNT_ID
en las variables de entorno (.env
&wrangler.toml
)

- Crea un token de API en Cloudflare R2.

- Obtén el ID de Clave de Acceso y la Clave de Acceso Secreta de Cloudflare R2 y guárdalos como
AWS_KEY_ID
yAWS_SECRET_ACCESS_KEY
en las variables de entorno (.env
&wrangler.toml
) respectivamente.

Generar las URLs pre-firmadas
1. Acceder a las Variables de Entorno
El primer paso es acceder a las variables de entorno necesarias durante el tiempo de ejecución para crear un Cliente AWS a través de aws4fetch. Desde Astro 5.6 en adelante, la forma en que deseas acceder a las variables de entorno en tiempo de ejecución en tu código es usando la función getSecret
de astro:env/server
para mantener las cosas independientes del proveedor. Esto es crucial para almacenar información sensible de manera segura sin codificarla directamente en tu aplicación. Recuperarás las siguientes variables:
- ID de Clave de Acceso de Cloudflare R2 (como
AWS_KEY_ID
) - Nombre del Bucket de Cloudflare (como
AWS_S3_BUCKET_NAME
) - Clave de Acceso Secreta de Cloudflare R2 (como
AWS_SECRET_ACCESS_KEY
) - ID de Cuenta de Cloudflare R2 (como
CLOUDFLARE_R2_ACCOUNT_ID
)
import { getSecret } from 'astro:env/server'
const accessKeyId = getSecret('AWS_KEY_ID')const s3BucketName = getSecret('AWS_S3_BUCKET_NAME')const secretAccessKey = getSecret('AWS_SECRET_ACCESS_KEY')const r2AccountId = getSecret('CLOUDFLARE_R2_ACCOUNT_ID')
2. Definir el Cliente AWS
A continuación, definirás la función defineAws4Fetch
que crea una instancia de cliente AWS. Esta función verifica si las credenciales AWS requeridas están configuradas y devuelve una nueva instancia de AwsClient
configurada para R2.
import { AwsClient } from 'aws4fetch'
// ...Existing 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({ accessKeyId, secretAccessKey, service: 's3', region: 'auto', })}
3. Determinar las URLs de R2
Necesitarás generar URLs únicas para cada carga de archivo a Cloudflare R2. La función getR2URL
a continuación se encarga de construir la URL correcta basada en el nombre del archivo y el nombre del bucket.
// ...Existing Code...
function getR2URL({ Key }: { Key: string }) { if (!s3BucketName) { throw new Error(`AWS_S3_BUCKET_NAME environment variable(s) are not set.`) } return new URL(`https://${r2AccountId}.r2.cloudflarestorage.com/${s3BucketName}/${Key}`)}
4. URL pre-firmada para OBTENER un Objeto R2 (recuperar)
La función getR2ObjectURL
a continuación recupera una URL pre-firmada de un objeto desde Cloudflare R2. Genera una solicitud firmada que te permite acceder al archivo de manera segura.
// ...Existing Code...
export async function getR2ObjectURL(Key: string) { try { const endpointUrl = getR2URL({ 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. URL pre-firmada para PONER un Objeto R2 (cargar)
La función uploadR2ObjectURL
a continuación es responsable de generar una URL pre-firmada para cargar un archivo a Cloudflare R2. Sigue una estructura similar a la función getR2ObjectURL
, generando una URL firmada que te permite cargar archivos de manera segura.
export async function uploadR2ObjectURL(file: { name: string; type: string }) { try { const Key = file.name const endpointUrl = getR2URL({ 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. Crear un Endpoint de Servidor (una Ruta API) en Astro
import type { APIContext } from 'astro'import { getR2ObjectURL, uploadR2ObjectURL } from '../../storage/r2'
// Define an asynchronous function named GET that accepts a request object.export async function GET({ request }: APIContext) { // Extract the 'file' parameter from the request URL. const url = new URL(request.url) const file = url.searchParams.get('file') // Check if the 'file' parameter exists in the URL. if (file) { try { const filePublicURL = await getR2ObjectURL(file) // Return a response with the image's public URL and a 200 status code. return new Response(filePublicURL) } catch (error: any) { // If an error occurs, log the error message and return a response with a 500 status code. const message = error.message || error.toString() console.log(message) return new Response(message, { status: 500 }) } } // If the 'file' parameter is not found in the URL, return a response with a 400 status code. return new Response('Invalid Request.', { status: 400 })}
export async function POST({ request }: APIContext) { // Extract the 'file' parameter from the request 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 { // Generate an accessible URL for the uploaded file // Use this url to perform a GET to this endpoint with file query param valued as below const publicUploadUrl = await uploadR2ObjectURL({ type, name }) // Return a success response with a message return new Response(publicUploadUrl) } catch (error: any) { // If there was an error during the upload process, return a 403 response with the error message const message = error.message || error.toString() console.log(message) return new Response(message, { status: 500 }) }}
Desplegar en Cloudflare Workers
Para hacer que tu aplicación sea desplegable en Cloudflare Workers, crea un archivo llamado .assetsignore
en el directorio public
con el siguiente contenido:
_routes.json_worker.js
A continuación, necesitarás usar la CLI de Wrangler para desplegar tu aplicación en Cloudflare Workers. Ejecuta el siguiente comando para desplegar:
npm run build && npx wrangler@latest deploy
Referencias
Conclusión
En esta publicación de blog, aprendiste cómo integrar Cloudflare R2 con Astro y Cloudflare Workers para cargas y recuperaciones de archivos. Siguiendo los pasos de implementación, puedes cargar y recuperar archivos de Cloudflare R2 de manera segura, asegurando que tu aplicación web tenga una solución de almacenamiento robusta y flexible.
Si deseas explorar secciones específicas con más detalle, ampliar ciertos conceptos o cubrir temas adicionales relacionados, por favor házmelo saber, ¡y estaré encantado de ayudar!