Agregar la búsqueda de tickets a un Worker

CloudflareBeginner
Practicar Ahora

Introducción

Una API de soporte necesita encontrar tickets abiertos y crear, actualizar y eliminar registros individuales de forma segura. Conectará un Worker a D1, implementará acceso SQL parametrizado y probará cómo gestiona la API los registros ausentes y las entradas no válidas.

El enrutador HTTP ya está incluido, por lo que la tarea principal es integrar la base de datos. Este laboratorio independiente utiliza un Worker desechable y una base de datos D1, además de datos locales separados.

Use su propia cuenta de aprendizaje y una VM nueva. Primero, la configuración prepara Node.js 22.22.0 y después ejecuta npm install para instalar Wrangler 4.131.1, específico del proyecto, y las dependencias de evaluación en /home/labex/project/ticket-database. Las versiones de las dependencias directas están fijadas y la instalación crea su propio archivo de bloqueo. Durante la configuración no se inicia sesión en la nube ni se realizan operaciones evaluadas en la base de datos. En una máquina personal, instale la misma versión de Wrangler con npm install --save-dev wrangler@4.131.1 en su proyecto.

Este ejercicio utiliza registros sintéticos pequeños dentro de las asignaciones gratuitas de D1. El uso existente de la cuenta cuenta para esas asignaciones. No necesita un dominio comprado. Conserve esta VM hasta comprobar tanto la eliminación de los recursos como el cierre de sesión.

Autorice esta VM y seleccione la cuenta

En este paso, conectará este terminal nuevo a su propia cuenta de aprendizaje. Iniciar sesión en el Dashboard por sí solo no autoriza la VM. El permiso de D1 permite crear bases de datos, modificar SQL y eliminarlas; el permiso de Workers permite realizar implementaciones; y el permiso de KV permite que Wrangler mantenga un inventario para la limpieza. Revise la página de consentimiento real, incluido Background Access, antes de autorizar.

Abra el proyecto preparado e inspeccione la versión fijada de la CLI:

cd /home/labex/project/ticket-database
npx wrangler --version

Debe aparecer 4.131.1. Inicie la autorización mediante dispositivo; --device muestra un código para el navegador y --browser=false le permite elegir cómo abrir el navegador:

npx wrangler login --device --browser=false --scopes account:read user:read d1:write workers_scripts:write workers_kv:write

Abra en el navegador la URL mostrada, introduzca el código actual, confirme su cuenta de aprendizaje y los permisos, y autorice el acceso. Espere a que el terminal confirme que la operación se realizó correctamente. Nunca pegue contraseñas ni tokens en archivos del proyecto.

npx wrangler whoami --json

Compruebe loggedIn: true y lea los valores name e id de la cuenta, aunque solo aparezca una cuenta. Copie el ID deseado en la configuración siguiente. La variable de shell siguiente usa 6 bytes aleatorios (12 caracteres hexadecimales) para evitar colisiones con otros estudiantes. Un documento aquí escribe el JSON situado entre las líneas JSON; $RUN se expande dentro de él.

La barra invertida delante de $schema conserva esa clave JSON literalmente; $RUN sigue expandiéndose al nombre único de esta ejecución.

RUN=labex-c04-d02-$(openssl rand -hex 6)
cat > wrangler.jsonc <<JSON
{
  "\$schema": "./node_modules/wrangler/config-schema.json",
  "name": "$RUN",
  "account_id": "YOUR_ACCOUNT_ID",
  "main": "src/index.js",
  "compatibility_date": "2026-09-15",
  "workers_dev": true,
  "preview_urls": false
}
JSON

Reemplace YOUR_ACCOUNT_ID antes de ejecutar el bloque. Mantenga abierto este terminal para que RUN siga disponible. name identifica esta ejecución; account_id selecciona la cuenta para las operaciones en la nube. El archivo es JSON normal, que también es válido como JSONC. Escribirlo no implementa ningún Worker.

Prepare datos locales y remotos independientes

En este paso, creará la conexión con D1 y cargará datos iniciales en la tabla de tickets conocida. La configuración proporciona el enrutamiento HTTP y la validación de entradas en src/index.js; las funciones de almacenamiento que faltan están en src/store.js. Así, su trabajo se concentra en el acceso SQL.

Cree una base de datos en la nube desechable. --binding DB proporciona al código de la aplicación un nombre corto, --update-config guarda su nombre real y su UUID en wrangler.jsonc, y --use-remote=false mantiene el desarrollo en local:

npx wrangler d1 create "$RUN-db" --binding DB --update-config --use-remote=false

Lea el nombre y el ID creados y, después, inspeccione el binding guardado:

cat wrangler.jsonc

La entrada DB debe indicar la base de datos de esta ejecución. Un binding es una conexión configurada entre el código y un recurso. Su UUID identifica la base de datos en la nube, mientras que --local utiliza una base de datos SQLite independiente en esta VM. Incluya siempre --local o --remote en los comandos SQL.

cat schema.sql
npx wrangler d1 execute DB --local --file schema.sql
npx wrangler d1 execute DB --remote --file schema.sql

Ahora cada destino contiene los mismos dos tickets iniciales. DB es el nombre que el controlador proporcionado recibe como env.DB; debe coincidir con el binding de la configuración.

Implemente operaciones CRUD parametrizadas

En este paso, implementará CRUD: crear, leer, actualizar y eliminar. Una sentencia preparada mantiene separadas la estructura SQL y la entrada. Cada ? es un marcador de posición para un parámetro; .bind(...) proporciona los valores en orden. Nunca concatene entradas del usuario en SQL, aunque parezcan inofensivas.

WHERE restringe los registros afectados. .all() devuelve un objeto de resultados cuyo campo results contiene el arreglo de filas. .first() devuelve una fila o null. La cláusula RETURNING de SQLite devuelve la fila modificada sin necesidad de realizar otra consulta. Para eliminar, .run() expone meta.changes, que indica al enrutador si el registro existía realmente.

Escriba el módulo de almacenamiento:

cat > src/store.js <<'JS'
export async function list(db, status) {
  const query = status === null
    ? db.prepare('SELECT id, subject, status, source FROM tickets ORDER BY id')
    : db.prepare('SELECT id, subject, status, source FROM tickets WHERE status = ? ORDER BY id').bind(status);
  const { results } = await query.all();
  return results;
}
export async function get(db, id) {
  return db.prepare('SELECT id, subject, status, source FROM tickets WHERE id = ?').bind(id).first();
}
export async function create(db, subject) {
  return db.prepare("INSERT INTO tickets (subject, source) VALUES (?, 'api') RETURNING id, subject, status, source").bind(subject).first();
}
export async function update(db, id, status) {
  return db.prepare('UPDATE tickets SET status = ? WHERE id = ? RETURNING id, subject, status, source').bind(status, id).first();
}
export async function remove(db, id) {
  const result = await db.prepare('DELETE FROM tickets WHERE id = ?').bind(id).run();
  return result.meta.changes === 1;
}
JS

Lea src/index.js para ver cómo el enrutamiento proporcionado utiliza estas funciones. Los registros ausentes se convierten en una respuesta 404 controlada; las entradas con formato incorrecto se convierten en 400; y un fallo de base de datos capturado se convierte en 503 sin exponer detalles internos de SQL.

Inicie el servidor local como un trabajo en segundo plano para mantener disponible el terminal:

npx wrangler dev --ip 0.0.0.0 > dev.log 2>&1 &

Lea el registro de inicio y espere al mensaje que indique que el servidor está escuchando:

cat dev.log
curl -i http://localhost:8787/tickets?status=open

Debe recibir HTTP 200 y únicamente el ticket 1. El servidor utiliza la base de datos local. Conserve el número de trabajo que muestra el terminal para usarlo durante la limpieza.

Pruebe escrituras y entradas rechazadas en local

En este paso, probará algo más que lecturas correctas. curl -i muestra el estado HTTP y las cabeceras; -H proporciona el tipo de contenido JSON y -d envía un cuerpo, usando POST de forma predeterminada.

Cree un asunto que contenga signos de puntuación parecidos a SQL:

curl -i http://localhost:8787/tickets -H 'Content-Type: application/json' -d "{\"subject\":\"Printer ' OR 1=1 --\"}"

Debe recibir 201 y el asunto debe conservarse como datos. Copie el id numérico devuelto en TICKET_ID; no suponga que los ID serán iguales después de repetir las pruebas:

TICKET_ID=YOUR_RETURNED_ID
curl -i http://localhost:8787/tickets/$TICKET_ID
curl -i -X PATCH http://localhost:8787/tickets/$TICKET_ID -H 'Content-Type: application/json' -d '{"status":"closed"}'
curl -i -X DELETE http://localhost:8787/tickets/$TICKET_ID
curl -i http://localhost:8787/tickets/$TICKET_ID

Debe obtener una lectura 200, una actualización 200 con closed, una eliminación 204 sin cuerpo y, después, una respuesta 404 con {"error":"not_found"}. Los dos tickets originales deben permanecer intactos.

Envíe JSON con formato incorrecto y un estado no válido:

curl -i http://localhost:8787/tickets -H 'Content-Type: application/json' -d '{'
curl -i -X PATCH http://localhost:8787/tickets/1 -H 'Content-Type: application/json' -d '{"status":"lost"}'

Debe recibir HTTP 400 con invalid_json y invalid_status, respectivamente. La parametrización SQL evita que la entrada se convierta en SQL, mientras que la validación de la aplicación rechaza los valores que están fuera de las reglas del negocio. Resuelven problemas diferentes.

Implemente y pruebe la base de datos vinculada

En este paso, publicará el controlador y su binding de D1. La base de datos ya contiene los datos iniciales en remoto; la implementación no copia las filas locales.

npx wrangler deploy

Copie la URL real https://...workers.dev que muestra la implementación en una variable de shell. Esta es una API sintética desechable, así que elimínela después de probarla:

URL='YOUR_DEPLOYED_HTTPS_URL'
curl -i "$URL/tickets?status=open"

Debe recibir 200 y el ticket 1. Si una implementación nueva devuelve temporalmente un error de la plataforma, espere unos segundos y repita esta lectura durante un máximo de un minuto. Continúe solo cuando coincidan tanto el estado como el JSON; los fallos persistentes requieren investigación.

Repita las operaciones CRUD en la API remota y copie el ID que esta devuelva:

curl -i "$URL/tickets" -H 'Content-Type: application/json' -d '{"subject":"Remote test"}'
TICKET_ID=YOUR_RETURNED_ID
curl -i -X PATCH "$URL/tickets/$TICKET_ID" -H 'Content-Type: application/json' -d '{"status":"closed"}'
curl -i -X DELETE "$URL/tickets/$TICKET_ID"
curl -i "$URL/tickets/$TICKET_ID"
curl -i "$URL/tickets"

Debe obtener 201, 200, 204, 404 y, finalmente, los dos tickets iniciales sin cambios. En el Dashboard, abra este Worker exacto y su vista Bindings. Confirme que DB apunta a su base de datos; siga el enlace de la base de datos para realizar una inspección de solo lectura. Un binding local guardado no demuestra que la conexión implementada sea la correcta.

El Worker desplegado y su vínculo DB

Este ejemplo muestra el Worker desplegado conectado mediante DB a su base de datos D1. El sufijo aleatorio identifica esta ejecución de ejemplo; tus nombres serán distintos. El enlace Value de la tabla abre la base de datos seleccionada por el vínculo desplegado.

Elimine los recursos desechables

En este paso, eliminará únicamente los recursos de este laboratorio mientras la VM todavía está autorizada. Termine primero todas las comprobaciones funcionales. Conserve la configuración hasta completar la verificación de la eliminación.

npx wrangler delete

Confirme que solo aparece el nombre del Worker incluido en la configuración de esta ejecución.

npx wrangler d1 delete DB

Inspeccione la solicitud y confirme que solo corresponde a la base de datos de esta ejecución. Después, enumere las bases de datos:

npx wrangler d1 list --json

El nombre y el UUID de la base de datos que registró deben estar ausentes en una respuesta correcta. Es posible que permanezcan otros recursos. Un error de autenticación o de red no permite sacar conclusiones: resuelva el acceso y repita la lectura antes de continuar. Realice la verificación de este paso mientras todavía tenga la sesión iniciada.

Detenga también el trabajo de desarrollo local. Enumere los trabajos y finalice únicamente el trabajo wrangler dev que inició; reemplace %1 si su número de trabajo es diferente:

jobs
kill %1

Finalice la autorización de esta VM

En este paso, finalizará la autorización solo después de que la comprobación independiente de la eliminación se complete correctamente. El cierre de sesión elimina la autorización de Wrangler almacenada en esta VM; cerrar una VM por sí solo no limpia los recursos en la nube.

npx wrangler logout
npx wrangler whoami --json

Debe aparecer loggedIn: false. Esta consulta sin autenticación puede terminar con un código distinto de cero; eso solo es esperado cuando la respuesta estructurada indica explícitamente que la sesión se cerró. Complete la verificación y, después, cierre el entorno del laboratorio.

Resumen

Practicó cómo agregar la búsqueda de tickets a un Worker. Comprobó resultados observables de la base de datos, mantuvo explícitos la cuenta seleccionada y el estado local, y eliminó los recursos desechables antes de cerrar la sesión.