Building Microservices with Deno, Reno, and PostgreSQL


Building Microservices with Deno, Reno, and PostgreSQL

In this tutorial, we show you how to go about building microservices with Deno, and introduce you to Reno — a thin routing library for Deno. We’ll explore how we can use this newer JavaScript platform to build a microservice that exposes endpoints for acting on a database.

Deno is a JavaScript and TypeScript runtime from Node.js creator Ryan Dahl that aims to address some of the latter technology’s shortcomings, such as simplifying the module path lookup algorithm and more closely aligning the core APIs with their browser-based equivalents. Despite these fundamental differences, the potential applications of Deno and Node.js are mostly identical. One of Node’s core strengths lies in building HTTP services, and the same can be argued for Deno.

Writing HTTP Servers with std/http

Before we introduce a routing library or contemplate our data access layer, it would be useful to step back and build a simple HTTP server with the std/http module, which is part of Deno’s standard library. If you haven’t already, install Deno. In a Unix-type operating system, you can run:

$ curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.3.0

Note that this tutorial has been developed against 1.3.0 (and std 0.65.0 as we’ll see later), but any later 1.x versions you may be using should be compatible. Alternatively, if you’re running an older version of Deno, you can upgrade to 1.3.0 with the deno upgrade command:

deno upgrade --version 1.3.0

You can verify that the expected Deno version has been installed with deno --version.

We’re now in a position to build an HTTP server. Create a directory, within your usual development directory, named deno-hello-http, and open it in your editor. Then, create a file called server.ts, and use the listenAndServe function within std/http to build our server:

import  listenAndServe  from "https://deno.land/std@0.65.0/http/mod.ts";

const BINDING = ":8000";

console.log(`Listening on $BINDING...`);

await listenAndServe(BINDING, (req) => 
  req.respond( body: "Hello world!" );
);

Developer Experience Protips

If you’re using VS Code, I’d heavily recommend the official Deno extension, which provides support for Deno’s path resolution algorithm. Additionally, you can run deno cache server.ts to install the dependencies and their TypeScript definitions, the latter serving as an invaluable API guide when writing your code.

We can start our server by running deno run --allow-net server.ts in our shell. Note the --allow-net permissions flag, granting our program with network access. Once listening on port 8000, we can target it with a HTTP request:

$ curl -v http://localhost:8000/ ; echo

> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 12
<

Hello world!

Great! With a few lines of TypeScript, we’ve been able to implement a simple server. That said, it isn’t particularly well-featured at this point. Given that we consistently serve "Hello world!" from our callback function, the same response will be returned for any endpoint or HTTP method. If we hit a server with POST /add, we’ll receive the same headers and body:

$ curl -v -d '' http://localhost:8000/add ; echo

> POST /add HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 200 OK
< content-length: 12
<

Hello world!

We can limit the existing response to GET / by conditionally checking the url and method properties of our callback’s req parameter:

import 
  listenAndServe,
  ServerRequest,
 from "https://deno.land/std@0.65.0/http/mod.ts";

const BINDING = ":8000";

console.log(`Listening on $BINDING...`);

function notFound( method, url : ServerRequest) 
  return 
    status: 404,
    body: `No route found for $method $url`,
  ;


await listenAndServe(BINDING, (req) => 
  const res = req.method === "GET" && req.url === "/"
    ?  body: "Hello world" 
    : notFound(req);

  req.respond(res);
);

If we restart our server, we should observe that GET / works as expected, but any other URL or method will result in a HTTP 404:

$ curl -v -d '' http://localhost:8000/add ; echo

> POST /add HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 2
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 404 Not Found
< content-length: 28
<

No route found for POST /add

std/http Beyond Simple Services

Bootstrapping trivial HTTP servers with Deno and std/http has proven to be relatively straightforward. How does this approach scale for more complex services?

Let’s consider a /messages endpoint that accepts and returns user-submitted messages. Following a RESTful approach, we can define the behavior of this endpoint and of our service overall:

Continue reading
Building Microservices with Deno, Reno, and PostgreSQL
on SitePoint.

Leave a Reply

Your email address will not be published. Required fields are marked *