Skip to content

REST

Un servidor web se puede configurar como un servidor de recursos que se accede mediante un conjunto de funciones “externas” o endpoints (API)

REST (Representational State Transfer) es una forma bastante habitual de interacción entre aplicaciones y servicios de cliente mediante HTTP.

Una solicitud HTTP se compone de un método y un “path”.

Por defecto, los navegadores utilizan el método GET, y cuando navegas a un sitio web lo haces con una petición GET y sólo tienes que indicar el “path”.

Pero una API web utiliza otros métodos, y los clientes utilizan esos métodos para realizar otras acciones que no són obtener recursos.

En este enlace tienes un proyecto de ayuda https://gitlab.com/xtec/typescript/hono (TODO Move a rest)

Crea una aplicación (con el template cloudflare-workers)

> bun create hono@latest hono
...
✔ Which template do you want to use? cloudflare-workers

Ejecuta el servidor en modo desarrollo:

> bun run dev
...
⎔ Starting local server...
[wrangler:inf] Ready on http://127.0.0.1:8787
...

Modifica el fichero index.ts para que devuelva un documento JSON en el path /api/hello:

import { Hono } from 'hono'
const app = new Hono()
app.get('/api/hello', (c) => {
return c.json({
ok: true,
message: 'Hello Hono!',
})
})
export default app

Instala curlie

Terminal window
scoop install curlie

Haz una petición GET:

Terminal window
curlie localhost:8787/api/hello

Puedes ver que el servidor devuelve la respuesta JSON que has programado:

Terminal window
HTTP/1.1 200 OK
Content-Length: 35
Content-Type: application/json
{
"ok": true,
"message": "Hello Hono!"
}

Una API web se compone de diferentes funciones “externas” definidas mediante un “path”.

La mayoría de las funciones, para ser útiles, deben estar parametrizadas: deben poder recibir unos parámetros y producir un resultado diferente en función de estos parámetros.

Puedes utilizar una parte del path para identificar la función, y la otra parte del path puedes utilizarlo para definir los parámetros de entrada.

Por ejemplo, si tienes una función que muestra el perfil de cada empleado puedes utilizar el path /employee/:id, donde /employee es el nombre externo de la función y /:id es el argumento de la función.

index.ts
const employees = {1: {name: "David"}, 2: {name: "Dora"}}
app.get('employee/:id', (c) => {
const {id} = c.req.param()
return c.json({employees.id})
})

Mover documentación de Rest y FastApi

app.get('/student/:username', (c) => {
const {username} = c.req.param()
return c.json({"student": username})
})
> curl http://127.0.0.1:8787/student/eva

Getting a path parameter, URL query value, and appending a Response header is written as follows.

app.get('/post/:id', (c) => {
const page = c.req.query('page')
const id = c.req.param('id')
c.header('X-Message', 'Hi!')
return c.text(`You want to see ${page} of ${id}`)
})

We can easily handle POST, PUT, and DELETE not only GET.

app.post('/post/', (c) => c.text('Created!', 201))
app.delete('/post/:id', (c) =>
c.text(`${c.req.param('id')} is deleted!`)
)

html Helper

The html Helper lets you write HTML in JavaScript template literal with a tag named html.

You have to escape these strings by yourself.

import { Hono } from 'hono'
import { html} from 'hono/html'
const app = new Hono()
app.get('/student/:username', (c) => {
const { username } = c.req.param()
return c.html(
html`<!doctype html>
<h1>Hello, ${username}!</h1>`
)
})

Using raw(), the content will be rendered as is.

If you want to use TSX, rename the file to src/index.tsx and configure it (check with each runtime as it is different).

or using JSX syntax.

Below is an example using JSX.

const View = () => {
return (
<html>
<body>
<h1>Hello Hono!</h1>
</body>
</html>
)
}
app.get('/page', (c) => {
return c.html(<View />)
})

Añade una dependencia con mongodb:

Terminal window
bun add mongodb

Node.js compatibility is required for database drivers, including Postgres.js, and needs to be configured for your Workers project.

Modifica el fichero wrangler.jsonc:

// wrangler.jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "hono",
"main": "src/index.ts",
"compatibility_date": "2025-04-10",
"compatibility_flags": [
"nodejs_compat"
]
}

Crea el fichero .dev.vars para desarrollo local:

.dev.vars
DB_CONN_STRING="mongodb+srv://<username>:<password>@cluster.2hr0xbm.mongodb.net"

Para obtener el valor de esta variable utiliza el “Adapter Helper” de Hono.

The env() function facilitates retrieving environment variables across different runtimes:

import {Hono} from 'hono'
import {env} from 'hono/adapter'
const app = new Hono()
app.get('/api/env', (c) => {
const {DB_CONN_STRING} = env<{ DB_CONN_STRING: string }>(c)
return c.json({DB_CONN_STRING: DB_CONN_STRING})
})

Ejecuta curlie en el endpoint

Terminal window
curlie localhost:8787/api/env

Puedes ver que responde con el string de conexión configurado con el fichero .dev.vars

HTTP/1.1 200 OK
Content-Length: 133
Content-Type: application/json
{
"DB_CONN_STRING": "mongodb+srv://<user>:<password>@cluster.ee8smuy.mongodb.net/?retryWrites=true&w=majority&appName=cluster"
}

Implementa un “endpoint” para insertar pájaros:

index.ts
app.post('/api/bird/', async (c) => {
const bird = await c.req.json()
const {DB_CONN_STRING} = env<{ DB_CONN_STRING: string }>(c)
const client = new MongoClient(DB_CONN_STRING)
const result = await client.db('earth').collection('birds').insertOne(bird)
return c.json({id: result.insertedId})
})

Desde el terminal, envia una petición POST al endpoint /api/bird/

Terminal window
curlie POST localhost:8787/api/bird/ name=swallow

Verifica que la base de datos tiene una golondrina en la colección birds.

A continuación implementa un “endpoint” para buscar pájaros por nombre:

index.ts
app.get('/api/bird/:name', async (c) => {
const {name} = c.req.param()
const {DB_CONN_STRING} = env<{ DB_CONN_STRING: string }>(c)
const result = await new MongoClient(DB_CONN_STRING).db('earth').collection('birds').findOne({ name })
if (result == null){
c.notFound()
} else {
return c.json(result)
}
})

Puedes buscar un pájaro por nombre:

Terminal window
curlie localhost:8787/api/bird/swallow
HTTP/1.1 200 OK
Content-Length: 51
Content-Type: application/json
{
"_id": "68079db611c9e476456f5cbb",
"name": "swallow"
}

I si no lo encuentra el “endpoint” devuelve un error:

Terminal window
curlie localhost:8787/api/bird/turtle
404 Not Found

A continuación despliega el proyecto en Cloudflare.

Primero tienes que añadir la variable DB_CONN_STRING a tu entorno de producción:

Terminal window
bunx wrangler secret put DB_CONN_STRING
× Enter a secret value: mongodb+srv://<user>:<password>@cluster.ee8smuy.mongodb.net

Despliega el código en Cloudflare:

> bun run deploy
...
Deployed hono triggers (2.64 sec)
https://hono.optersoft.workers.dev
Current Version ID: bbaafdcb-5836-4ab8-a360-bc65832aabd2

Ves a la URL que se te indica (en tu caso será diferente): https://hono.optersoft.workers.dev

Puedes ver que la aplicación se ha desplegado en Cloudflare Workers.