Using Deno.close to close resources

Mayank C
Tech Tonic

--

Introduction

In Deno, resources are one of the basic building blocks that represent things like input, output, client connections, server socket, files, web socket, etc. All the resources have a simple incrementing resource ID.

There are standard resources like stdin, stdout, and stderr that are opened at startup time. The standard resource IDs are:

  • 0: stdin
  • 1: stdout
  • 2: stderr

All the other resources like client connections, server sockets, file, etc. need to be opened explicitly. The opening of resource varies as per the type of resource. The resource IDs for these resources start from 3 and increments by 1.

Just like opening, a resource also needs to be closed. In the majority of cases, a resource is closed after its use. Sometimes closing is done internally (for example-HTTP response closes the connection), and sometimes closing is explicitly (closing the file resource). In some cases, a resource can be closed if that resource is no longer needed to be open.

In this article, we’ll go over a generic function Deno.close that is useful in closing any type of resource. We’ll be discussing explicit closure only.

Deno.close

Deno.close is part of the core runtime, so there is no need to import anything. Deno.close is a synchronous function. There is no async variant.

Inputs & Outputs

The only input is resource ID. There is no output.

function close(rid: number): void;

Use-cases

Deno.close is a generic function that can be used to close any resource. It is not dependent on the type of resource. Let’s go over some use-cases and see how explicit closure can help.

Closing input (stdin)

The stdin resource represents the standard input stream of the process. This is useful for CLI applications, but is of no use for background applications. In such cases, stdin can be closed at startup.

Deno.close(Deno.stdin.rid);

If we try to read after closure, a BadResource error would be thrown.

Deno.close(Deno.stdin.rid);
prompt('abcd');
//error: Uncaught BadResource: Bad resource ID

Closing output (stdout)

Just like stdin, stdout represents the standard output stream of the process. This is again useful for CLI apps, but not for background apps as they would write into a log file.

Deno.close(Deno.stdout.rid);

Closing error (stderr)

Similarly, stderr can be closed at startup as all the errors would go to the log file too.

Deno.close(Deno.stderr.rid);

Closing file

A file resource that’s explicitly opened needs an explicit closure. There are helper functions like Deno.readTextFile that takes care of opening, reading, and closing. Such functions don’t need explicit closure. In other cases, a file needs to be explicitly closed.

const f=await Deno.create('./abcd');
//do something on f
Deno.close(f.rid);

Closing TCP connection

A TCP connection needs explicit closure, unless it’s closed internally by the helper functions. For example-respondWith function closes the underlying TCP connection. However, there might be cases when a server accepts connections only from whitelisted IPs. Any connection request from unrecognized IP could be aborted immediately.

const whitelisted:Array<string>=['10.0.0.1'];
const listener = Deno.listen({ port: 3000 });
for await(const conn of listener)
if(!whitelisted.includes(conn.remoteAddr.hostname))
Deno.close(conn.rid);

Here is a run using curl command:

curl http://localhost:3000 -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3000 (#0)
> GET / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.64.1
> Accept: */*
>
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

--

--