To be honest, I prefer the NodeJS runtime over JavaScript itself. While JS is great, I appreciate the added benefits of type validation and similar features. During my student days, I heavily used C# to build everything from desktop apps to web services, which is probably why I love TypeScript.
Today, I'll show you how to create a Rest API using Deno and TypeScript. It's a powerful combination that I'm excited to share with you.
What is Deno?
Deno is a secure and modern JavaScript/TypeScript runtime created by Ryan Dahl, the same person who created Node.js. It allows you to run JavaScript and TypeScript code outside a web browser, with built-in support for modules, TypeScript, and other valuable features. Deno is becoming increasingly popular among developers due to its security, simplicity, and ease of use.
By the way, if you are struggling with which language to learn first, check out my article about that: Choosing Your First Programming Language: A Beginner’s Guide.
Why Deno?
As I said before, I love TypeScript. Deno allows to run TypeScript directly without compilation in JavaScript.
One more reason is more personal. I like all ideas around Deno project. It would be great to try it with you.
Our Goal
We aim to create a REST API for generating "lorem ipsum" text via user requests. As part of the development process, we'll be implementing a basic security feature: API key validation.
Installing Deno
Deno installation is a simple process. There is an install script that could help do that on different platforms. I like Deno distribution idea like "one single executable". That makes more simple to deploy and use Deno.
Creating project
I suppose you have installed Deno and are ready to continue. Let's create a new directory for our project and then run deno init
.
mkdir lorem-ipsum-api-deno-typescript cd lorem-ipsum-api-deno-typescript deno init
Let's try to run a boilerplate.
deno run main.ts
Excellent, it's working. Now we are ready to move forward.
Create HTTP end-point
Let's create HTTP end-point. We will use Oak framework for that. Oak is similar to Express framework, which you maybe know because it is very popular in NodeJS community.
The basic code could look like the following.
// import Application class from Oak module import { Application as OakApp } from "https://deno.land/x/oak/mod.ts"; // create main function of our program export function runHttp(): void { // create new instance of Oak Application const app = new OakApp(); // add handler to our application app.use((ctx) => { ctx.response.body = "Hello World!"; }); // start our application and use promise to show server started or not app.listen({ port: 8000 }); // show message in console console.log("Server started on port 8000"); } // run main function if this file is executed directly // (not imported as a module) if (import.meta.main) { runHttp(); }
Let's run it and test it. We should add --allow-net parameter to deno run
command, because default Deno settings don't allow script access to the networking.
deno run --allow-net main.ts
Nice! Everything is working.
Adding router for lorem ipsum generation
Having all code inside one file and a single function isn't a good idea. Let's make a folder for routes and create there our first router.
// import Router class import {Router} from "https://deno.land/x/oak/mod.ts"; // create new class that extends Router class export class LoremIpsumRouter extends Router { // create constructor and init routes constructor() { super(); this.get("/lorem-ipsum/get-text", this.getText); } // create handler for GET /lorem-ipsum/get-text getText(ctx): void { ctx.response.body = "Lorem ipsum dolor sit amet..."; } }
Let's import it inside our app.
// import our router class import { LoremIpsumRouter } from "./routes/lorem-ipsum-router.ts";
And add using a new router by our app.
// create lorem ipsum router const loremIpsumRouter = new LoremIpsumRouter(); // add handler to our application app.use(loremIpsumRouter.routes()); app.use(loremIpsumRouter.allowedMethods());
Time to run and test.
Great! Everything is working fine.
Creating handling functions
Let's create a controllers directory and put code for handling requests there. I have created a separate class with static functions. We could use even just functions for that small project without creating classes. However, I put all handling functions inside the same class for a nice structure.
export class LoremIpsumController { public static getParagraphs(ctx): void { ctx.response.body = "Lorem ipsum dolor sit amet PARAGRAPHS..."; } public static getSentences(ctx): void { ctx.response.body = "Lorem ipsum dolor sit amet SENTENCES..."; } public static getWords(ctx): void { ctx.response.body = "Lorem ipsum dolor sit amet WORDS..."; } }
Now we can change a bit router to make it works with the newly created controller. I have added an optional parameter count to each one. That will allow our API users to specify the desired length of the requested text, sentences, or words. And I connected our controller to the router.
// import Router class import {Router} from "https://deno.land/x/oak/mod.ts"; import {LoremIpsumController} from "../controllers/lorem-ipsum-controller.ts"; // create new class that extends Router class export class LoremIpsumRouter extends Router { // create constructor and init routes constructor() { super(); this.get("/lorem-ipsum/paragraphs/:count?", LoremIpsumController.getParagraphs); this.get("/lorem-ipsum/sentences/:count?", LoremIpsumController.getSentences); this.get("/lorem-ipsum/words/:count?", LoremIpsumController.getWords); } }
Connect library for generating "lorem ipsum"
Thankfully for npm packages support in Deno we can use an existing library to generate the text. Let's use this package.
In Deno you don't need to install the package. For using lorem ipsum library, let's add those lines inside our controller file.
import { LoremIpsum } from 'npm:lorem-ipsum@2.0.8';
As you can see, it's easy to use npm package in Deno program. The syntax is easy npm:package-name@version
.
Controller code for the responses
Time to add actual code for generating the response. Here is our complete controller code.
import { LoremIpsum } from 'npm:lorem-ipsum@2.0.8'; export class LoremIpsumController { public static getParagraphs(ctx): void { const count = ctx.params.count ? parseInt(ctx.params.count) : 3; const lorem = new LoremIpsum(); ctx.response.body = lorem.generateParagraphs(count); } public static getSentences(ctx): void { const count = ctx.params.count ? parseInt(ctx.params.count) : 3; const lorem = new LoremIpsum(); ctx.response.body = lorem.generateSentences(count); } public static getWords(ctx): void { const count = ctx.params.count ? parseInt(ctx.params.count) : 3; const lorem = new LoremIpsum(); ctx.response.body = lorem.generateWords(count); } }
Pretty simple, yeah? Don't forget to convert the count parameter to a number because, by default, it's a string. Also, I added the default count value as 3.
Is it working? Of course, I have tested the system.
Auth for Deno Rest API
Oak framework allows us to make different auth mechanisms. However, I would like to stay with a pretty simple one. Let's make auth with hardcoded Bearer Token.
First, I created auth middlewares folder and file inside: middlewares/auth-middleware.ts. The code of the file is pretty simple.
export async function authMiddleware(ctx, next) { // get authorization header const authHeader = ctx.request.headers.get('authorization'); // check if authorization header exists and starts with Bearer if (!authHeader || !authHeader.startsWith('Bearer ')) { ctx.response.status = 401; ctx.response.body = {message: 'Unauthorized'};s return; } // get token from authorization header const token = authHeader.split(' ')[1]; // check if token is valid (in this case token is '123456789') if (token !== '123456789') { ctx.response.status = 403; ctx.response.body = {message: 'Forbidden'}; return; } // call next middleware await next(); }
But to make it work, we must add it to our app object. Let's edit the main.ts file a bit.
... // import our middleware import {authMiddleware} from "./middlewares/auth-middleware.ts"; ... // add our middleware to our application app.use(authMiddleware);
Looks good. Let's test it out.
Everything is fine.
Final?
As you can see, building web apps with Oak framework isn't complex. Honestly, it's the same as Express framework in NodeJS.
I hope today you learned something new and easy can build Deno Rest API by yourself. If you have any questions or want more articles about Deno, please write about it in the comments section.
If you want to have the full source code checkout this GitHub repository.
Top comments (0)