Routing
As you probably noticed from visiting the API page in the admin UI (http://localhost:8788/admin/api), there are many automatically generated endpoints that support CRUD (Create - Read - Update - Delete) operations on you database tables.
In order to create custom routes with custom business rules, we use SonicJs's routing system.
If you are already familiar with Node/Express, you'll be right at home as the concepts and syntax are very similar. Let's checkout a simple example:
router.get("/ping", (ctx) => {
return ctx.json({'date': Date()});
});
SonicJs uses HonoJs for its requests routing, a lightweight, ultra-fast web framework that supports various edge platforms including (you guessed it!) Cloudflare Workers.
So technically, SonicJs will run on anything that HonoJs runs on (Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Vercel, Lagon, AWS Lambda, Lambda@Edge, and Node.js). However, since we're obsessed with 🔥 speed 🔥, we're putting all focus on deploying to Cloudflare exclusively while the other providers play catch-up.
Hello World
Write your first custom set of routes in /src/custom/hello.ts
.
import { Hono } from 'hono'
const hello = new Hono()
hello.get('/', (c) => {
return c.text('Hello SonicJs!')
});
export { hello };
Next all we need to do it import our new hello router into our main server, so let's update src/server.ts
and
add the 2 lines marked with // <--- add this line
:
import { Hono } from "hono";
import { api } from "./cms/api/api";
import { Bindings } from "./cms/types/bindings";
import { admin } from "./cms/admin/admin";
import { content } from "./cms/api/content";
import { hello } from "./cms/api/hello"; // <--- add this line
const app = new Hono<{ Bindings: Bindings }>()
app.get("/", async (ctx) => {
return ctx.redirect('/admin');
});
app.get("/public/*", async (ctx) => {
return await ctx.env.ASSETS.fetch(ctx.req.raw);
});
app.route('/v1', api)
app.route('/v1/content', content)
app.route('/admin', admin)
app.route('/hello', hello) // <--- add this line
export default app;
Startup the app with npm run dev
and visit:
http://localhost:8788/v1/hello
Easy Peasy right! To continue, make sure you've ⭐⭐⭐⭐⭐ starred the repo on Github 🙏. Here at SonicJs we work for stars my friend 🤩.
Return JSON
Returning JSON is also easy. The following is an example of handling a GET Request to /v1/hello
and returning an application/json
Response. Don't forget to write return
.
app.get('/api/hello', (c) => {
return c.json({
ok: true,
message: 'Of course I talk to myself. Sometimes I need expert advice.',
})
})
Request and Response
Getting a path parameter, URL query value, and appending Response header:
app.get('/posts/:id', (c) => {
const page = c.req.query('page')
const id = c.req.param('id')
c.header('X-Message', 'Hi!')
return c.text(`You want see ${page} of ${id}`)
})
We can of course also handle POST, PUT, and DELETE:
app.post('/posts', (c) => c.text('Created!', 201))
app.delete('/posts/:id', (c) => c.text(`${c.req.param('id')} is deleted!`))
Return HTML
SonicJs is also suitable for returning HTML. This is how the admin section available at http://localhost:8788/admin
is generated. You can return any html you want, but in the case of the admin section,
we use React SSR. More info on that in the core developers guide.
const View = () => {
return (
<html>
<body>
<h1>Excuse my naivety. I was born at a very early age.</h1>
</body>
</html>
)
}
app.get('/page', (c) => {
return c.html(<View />)
})
Return raw Response
You can also return the raw Response.
app.get('/', (c) => {
return new Response("I’d agree with you, but then we’d both be wrong.")
})
Using Middleware
Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle.
For example, add the Basic Authentication:
import { basicAuth } from 'hono/basic-auth'
// ...
app.use(
'/admin/*',
basicAuth({
username: 'admin',
password: 'secret',
})
)
app.get('/admin', (c) => {
return c.text('Your are authorized!')
})
There are useful built-in middleware including Bearer and authentication using JWT, CORS and ETag. Also, we have third-party middleware using external libraries such as GraphQL Server and Firebase Auth. Additional, you can create your own middleware functions.
Adapter
There are Adapters for platform-dependent functions, e.g., handling static files.
For example, to handle static files in Cloudflare Workers, import hono/cloudflare-workers
.
import { serveStatic } from 'hono/cloudflare-workers'
app.get('/static/*', serveStatic({ root: './' }))
Need More?
SonicJs uses Hono for routing. Hono is an ultra fast routing system for edge frameworks. Please see their docs for any routing needs not covered in the above.