惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
量子位
V2EX - 技术
V2EX - 技术
K
Kaspersky official blog
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
I
Intezer
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
博客园 - Franky
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Recorded Future
Recorded Future
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Hacker News
The Hacker News
T
Tenable Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
雷峰网
雷峰网
WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Webroot Blog
Webroot Blog
L
LangChain Blog
C
Check Point Blog
N
News | PayPal Newsroom
L
LINUX DO - 热门话题
T
Tor Project blog
V
Visual Studio Blog
Microsoft Security Blog
Microsoft Security Blog
S
Security Affairs
Schneier on Security
Schneier on Security
Hacker News: Ask HN
Hacker News: Ask HN
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Security Latest
Security Latest
MyScale Blog
MyScale Blog
Cyberwarzone
Cyberwarzone
N
Netflix TechBlog - Medium
Scott Helme
Scott Helme
PCI Perspectives
PCI Perspectives
The Last Watchdog
The Last Watchdog
人人都是产品经理
人人都是产品经理
W
WeLiveSecurity

Deno

Deno 2.8 | Deno Claw Patrol: an open-source security firewall for agents | Deno Fresh 2.3: Zero JS by default, View Transitions, and Temporal support | Deno Deno 2.7: Temporal API, Windows ARM, and npm overrides | Deno Build a dinosaur runner game with Deno, pt. 6 | Deno Build a dinosaur runner game with Deno, pt. 5 | Deno Deno Deploy is Generally Available | Deno Introducing Deno Sandbox | Deno Build a dinosaur runner game with Deno, pt. 4 | Deno Build a dinosaur runner game with Deno, pt. 3 | Deno Build a dinosaur runner game with Deno, pt. 2 | Deno React / Next.js Denial-of-Service Vulnerability: Deno Deploy users protected | Deno Deno 2.6: dx is the new npx | Deno Build a dinosaur runner game with Deno, pt. 1 | Deno React Server Functions / Next.js Vulnerability: Deno Deploy users protected | Deno My highlights from the new Deno Deploy | Deno Deno's Other Open Source Projects | Deno How Deno protects against npm exploits | Deno Help Us Raise $200k to Free JavaScript from Oracle | Deno Deno 2.5: Permissions in the config file | Deno Fresh 2.0 Graduates to Beta, Adds Vite Support | Deno Deno 2.4: deno bundle is back | Deno JavaScript™ Trademark Update | Deno What's coming to JavaScript | Deno A brief history of JavaScript | Deno Reports of Deno's Demise Have Been Greatly Exaggerated | Deno An Update on Fresh | Deno How Plaid migrated 100 services to a new database platform 5x faster with Deno | Deno Deno 2.3: Improved deno compile, local npm packages, and more | Deno Add JSR packages with pnpm and Yarn | Deno Zero-config Debugging with Deno and OpenTelemetry | Deno Exploring Art with TypeScript, Jupyter, Polars, and Observable Plot | Deno Deno v Oracle Update 3: Fighting the JavaScript Trademark | Deno Build a custom RAG AI agent in TypeScript and Jupyter | Deno How to get deep traces in your Node.js backend with OTel and Deno | Deno toranoana.deno #20 登録受付中(2025年3月14日) | Deno Node just added TypeScript support. What does that mean for Deno? | Deno The Dino 🦕, the Llama 🦙, and the Whale 🐋 | Deno Publish a lint rule, get a prize | Deno Deno 2.2: OpenTelemetry, Lint Plugins, node:sqlite | Deno If you're not using npm specifiers, you're doing it wrong | Deno How Deno's documentation is evolving | Deno Oracle justified its JavaScript trademark with Node.js—now it wants that ignored | Deno Introducing the JSR open governance board | Deno Intro to Wasm in Deno | Deno Announcing OpenAI on JSR | Deno Deno in 2024 | Deno Goodbye WinterCG, welcome WinterTC | Deno Build a SolidJS app with Deno | Deno Run your Next.js SSR app on Deno Deploy | Deno Solve Advent of Code 2024 with Deno and Win Prizes! | Deno Deno v. Oracle: Canceling the JavaScript Trademark | Deno Deno 2.1: Wasm Imports and other enhancements | Deno Build a Typesafe API with tRPC and Deno | Deno Self-contained Executable Programs with Deno Compile | Deno Build a Database App with Drizzle ORM and Deno | Deno Introducing your new JavaScript package manager: Deno | Deno Announcing Growthbook on JSR | Deno Build an Astro site with Deno | Deno How to convert CommonJS to ESM | Deno Announcing Deno 2 | Deno The Final Touches: What’s New In v2.0.0-rc.10 | Deno Announcing Stable V8 Bindings for Rust | Deno Deno 2.0 Release Candidate | Deno Secure, efficient private npm registries with Cloudsmith and Deno | Deno Painting the Plane as We Fly It: Designing JSR | Deno Introducing Web Cache API support on Deno Deploy | Deno Deno 1.46: The Last 1.x Release | Deno Protect your cloud spend with new Deno Deploy spend limits | Deno What we got wrong about HTTP imports | Deno Benchmarking AWS Lambda Cold Starts Across JavaScript Runtimes | Deno Announcing Supabase on JSR | Deno Deno 1.45: Workspace and Monorepo Support | Deno Introducing KV Backup for Deno Subhosting | Deno A Gentle Intro to TypeScript | Deno Announcing Hono on JSR | Deno How We Made the Deno Language Server Ten Times Faster | Deno How the Guardian uses Deno to audit accessibility and performance across their 2.7 million articles | Deno Introducing More Flexible Domain Association for Deno Subhosting | Deno The stabilization process of the Standard Library has begun | Deno Deno 1.44: Private npm registries, improved Node.js compat, and performance boosts | Deno How we built a secure, performant, multi-tenant cloud platform to run untrusted code | Deno The Deno Standard Library is now available on JSR | Deno How to document your JavaScript package | Deno Your Low Code Solution Needs an Escape Hatch | Deno Deno 1.43: Improved Language Server performance | Deno How Slack used Deno to save months of engineering effort in launching their new platform | Deno JSR Is Not Another Package Manager | Deno Announcing the Hookdeck SDK on JSR | Deno Announcing the Neon Serverless Driver on JSR | Deno An intro to TSConfig for JavaScript Developers | Deno How we built JSR | Deno How Netlify used Deno Subhosting to build a successful edge functions product | Deno Introducing Simpler Project Creation in Deno Deploy | Deno Deno 1.42: Better dependency management with JSR | Deno Introducing deployctl, the command line interface for Deno Deploy | Deno Introducing JSR - the JavaScript Registry | Deno How to add Monaco to a Next.js app and securely run untrusted user code | Deno Survey Results and Roadmap | Deno Deno 1.41: smaller deno compile binaries | Deno
Build a REST API with Express, TypeScript, and Deno | Deno
Tim Post · 2023-03-08 · via Deno

There’s a lot of really great tutorials for anyone looking to get started building a REST API with TypeScript and Express. These tutorials, as great as they are, have two downsides:

  1. They require you to install and configure TypeScript, and ship everything required to accomplish that. This can be time-consuming and a source of frustration, particularly for new developers.

  2. They don’t address the need to be proactive about boxing in untrusted code; this isn’t surprising, as the majority of tooling doesn’t support it.

Which is why we have created this tutorial. With Deno, you don’t need to configure TypeScript, so you can get up and running with minimal dependencies.

Video Thumbnail Feel free to watch the video walkthrough of this post.

If you want to skip to the code, you can do so here.

Setting Up Express and its Types

Let’s create main.ts, which will contain the logic for our API.

In this file, let’s import Express through an npm specifier.

import express, { NextFunction, Request, Response } from "npm:express@4.18.2";

This gets us express, but not the type definitions. Let’s import the type definitions by adding this comment:


import express, { NextFunction, Request, Response } from "npm:express@4.18.2";

Next, we need to define a way to interact with Express’ application interface, and we’re going to need to define a port for it to run which we’ll get from the environment:

const app = express();
const port = Number(Deno.env.get("PORT")) || 3000;

Let’s define a test route that will say hello upon receiving a GET request, which we’ll just make the default base route for now:

app.get("/", (_req, res) => {
  res.status(200).send("Hello from Deno and Express!");
});

Now we’ve built the simple logic, we just need it to listen and start serving requests! For this we’ll use .listen() as shown:

app.listen(port, () => {
  console.log(`Listening on ${port} ...`);
});

And now we’re ready to go!

Starting the Server Securely

Let’s start our server:

Deno Permissions, "Deno Requesting Permissions"

We have to pull in all kinds of code when we’re developing APIs, from geo information, AI, ad servers and whatever other inputs have to come together to produce what’s required. Sure, we don’t anticipate Express introducing vulnerabilities, but Express is just one part of the stack you’re going to need to make something.

Had it requested access to system information, high resolution timers, or access outside of the directory, it would have been a red flag. You can specify permissions in a variety of ways, including the shebang in scripts.

At this point, we have a running API service that we can query with curl:

Deno Express Hello World, "Deno Saying Hello Through Express"

We’re now certain the framework is working correctly, so we’re sure about our installation and everything else. But, it’s not really a great working environment yet, so let’s set up our deno.jsonc file to define some helper scripts:

Deno Config Showing Tasks, "Deno.jsonc in vscode"

This works similar to package.json scripts (in fact, Deno can even use package.json scripts, but a deno.jsonc is recommended), where we have one task for development, and another to start the server without watching and reloading on changes.

Seeing the output of deno task, we can confirm that we have two scripts available:

$ deno task
Available tasks:
- dev
    deno run --allow-read --allow-net --allow-env --watch main.ts
- start
    deno run --allow-read --allow-net --allow-env main.ts

We can use deno task dev and deno task start, respectively.

Adding Logging

The next thing we’re going to need is some kind of logging functionality so that we can troubleshoot our requests while we’re building them, and that’s a great introduction into the concept of middleware in Express.

Middleware is a function that can read and even modify the req and res objects. We use middleware to do everything from logging to injecting headers, or even rate limiting and checking auth. Middleware must do one of two things when it’s done:

  • It must close the connection with a response if appropriate, or
  • It must call next(), which tells Express that it’s time to pass the objects to the next middleware function

Middleware takes 3 arguments: req and res as you’d expect, and also next, which points to the next appropriate middleware function (or returns control to the handler function).

Rather than console.log() something in every handler that we write, let’s define the first middleware function to be a logger, and tell Express that we’d like to use it. In main.ts:

const reqLogger = function (req, _res, next) {
  console.info(`${req.method} request to "${req.url}" by ${req.hostname}`);
  next();
};

You can have as much middleware as you want, and organize it in a way that works for you. Just remember that the speed of your responses depends on how quickly your middleware chain hands control back to the framework. Middleware is executed in the order that the framework is informed of it.

Generating Data

So we’re now in a pretty great place to start developing. Run the ./generate_data.ts command (deno run -A ./generate_data.ts if the shebang won’t work for you), which will generate some mock user data in data_blob.json that we can safely use like any other read-only data store safely through Deno’s import type assertions:

import demoData from "./data_blob.json" with { type: "json" };

We now have access to demoData.users in our handlers, so let’s write two handlers:

  • one /users which returns the entire contents of the users object, and
  • an additional dynamic route that allows us to look up a single user by ID
app.get("/users", (_req, res) => {
  res.status(200).json(demoData.users);
});

app.get("/users/:id", (req, res) => {
  const idx = Number(req.params.id);
  for (const user of demoData.users) {
    if (user.id === idx) {
      res.status(200).json(user);
    }
  }
  res.status(400).json({ msg: "User not found" });
});

We can also clear away the hello world default route, which leaves us with a nice API starting point:


import express, { NextFunction, Request, Response } from "npm:express@4.18.2";
import demoData from "./data_blob.json" with { type: "json" };

const app = express();
const port = Number(Deno.env.get("PORT")) || 3000;

const reqLogger = function (req, _res, next) {
  console.info(`${req.method} request to "${req.url}" by ${req.hostname}`);
  next();
};

app.use(reqLogger);

app.get("/users", (_req, res) => {
  res.status(200).json(demoData.users);
});

app.get("/users/:id", (req, res) => {
  const idx = Number(req.params.id);
  for (const user of demoData.users) {
    if (user.id === idx) {
      res.status(200).json(user);
    }
  }
  res.status(400).json({ msg: "User not found" });
});

app.listen(port, () => {
  console.log(`Listening on ${port} ...`);
});

Note the Hello, world! handler on / has been removed (and isn’t present in the linked repository).

What’s next?

We have a great starting point for a REST API in under 30 lines of code. Now, you can add a POST handler using app.post(), PUT handler with app.put(), or whatever other methods you want.

In a future post, we’ll cover how we can use Deno’s test runner and benchmark tools so we’re more comfortable taking our code from a proof of concept to something we’ll trust in production. We’ll end the series after that with ways that we can deploy our project.

Stuck? Get help in our Discord!