REST is a set of rules and recommendations for designing a web API.
On this page
Introduction
A web server can be configured as a resource server accessed through a set of “external” functions or endpoints (API).
REST is a fairly common way of interacting between client applications and services using HTTP.
An HTTP request consists of a method and a “path”.
By default, browsers use the GET method, and when you navigate to a website you do so with a GET request and only need to specify the “path”.
But a web API uses other methods, and clients use these methods to perform actions other than obtaining resources.
Work Environment
Create an application (with the cloudflare-workers template):
deno init --npm hono hono-rest --template cloudflare-workersRun the server in development mode:
deno task devModify the index.ts file to return a JSON document at the path /api/hello.
Add this code:
app.get('/api/hello', (c) => { return c.json({ ok: true, message: 'Hello Hono!', })})Install curlie:
scoop install curlieMake a GET request:
curlie localhost:8787/api/helloYou can see that the server returns the JSON response you programmed:
HTTP/1.1 200 OKContent-Length: 35Content-Type: application/json
{ "ok": true, "message": "Hello Hono!"}Routes
A web API consists of different “external” functions defined through a “path”.
Parameters
Most functions, to be useful, must be parameterized: they must be able to receive parameters and produce a different result based on those parameters.
You can use part of the path to identify the function and the other part of the path to define the input parameters.
For example, if you have a function that shows the profile of each employee, you can use the path /employee/:id, where /employee is the external name of the function and /:id is the function argument.
const employees = [{name: "David"}, {name: "Dora"}]
app.get('employee/:id', (c) => { const {id} = c.req.param() const index = parseInt(id) const employee = employees[index] if (!employee) { return c.json('Employee not found', 404) } else { return c.json(employee) }})Parameters
app.get('/student/:username', (c) => { const {username} = c.req.param() return c.json({"student": username})})> curl http://127.0.0.1:8787/student/evaGetting 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!`))MongoDB
Add a dependency with mongodb:
deno add npm:mongodbNode.js compatibility is required for database drivers, including Postgres.js, and needs to be configured for your Workers project.
Modify the wrangler.jsonc file:
// wrangler.jsonc{ "$schema": "node_modules/wrangler/config-schema.json", "name": "hono", "main": "src/index.ts", "compatibility_date": "2025-04-10", "compatibility_flags": [ "nodejs_compat" ]}Connection String
Create the .dev.vars file for local development:
DB_CONN_STRING="mongodb+srv://<username>:<password>@cluster.2hr0xbm.mongodb.net".gitignore To get the value of this variable, use Hono’s Adapter Helper.
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})})Run curlie at the endpoint:
curlie localhost:8787/api/envYou can see that it responds with the connection string configured in the .dev.vars file:
HTTP/1.1 200 OKContent-Length: 133Content-Type: application/json
{ "DB_CONN_STRING": "mongodb+srv://<user>:<password>@cluster.ee8smuy.mongodb.net/?retryWrites=true&w=majority&appName=cluster"}.dev.vars file to work with a local database or another database that is not the production one Let’s Go!
Implement an “endpoint” to insert birds:
import { MongoClient } from 'mongodb'
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})})From the terminal, send a POST request to the /api/bird/ endpoint:
curlie POST localhost:8787/api/bird/ name=swallowVerify that the database has a swallow in the birds collection.
Next, implement an “endpoint” to search for birds by name:
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) }})You can search for a bird by name:
curlie localhost:8787/api/bird/swallow
HTTP/1.1 200 OKContent-Length: 51Content-Type: application/json
{ "_id": "68079db611c9e476456f5cbb", "name": "swallow"}And if it doesn’t find it, the endpoint returns an error:
curlie localhost:8787/api/bird/turtle
404 Not FoundCloudflare
Next, deploy the project to Cloud - Cloudflare.
First, you need to add the DB_CONN_STRING variable to your production environment:
deno run -A npm:wrangler secret put DB_CONN_STRING
× Enter a secret value: mongodb+srv://<user>:<password>@cluster.ee8smuy.mongodb.netDeploy the code to Cloudflare:
deno task deploy...Deployed hono triggers (2.64 sec) https://hono.optersoft.workers.devCurrent Version ID: bbaafdcb-5836-4ab8-a360-bc65832aabd2Go to the URL indicated to you (it will be different in your case): https://hono.optersoft.workers.dev
You can see that the application has been deployed to Cloudflare Workers.
deno task deploy Secrets are a type of binding that allow you to attach encrypted text values to your Worker.