TypeScriptでexpressを使ってAPIサーバを作る

初期設定

とりえあえず、TypeScriptとexpressとexpressの型定義をインストールする。

npm i express
npm i -D typescript
npm i -D @types/express

はじめの一歩

expressを用いたWebアプリでは、expressのオブジェクトを作り、そのオブジェクトにどのメソッドでどのURLに対してどんなリクエストが来たらどんなレスポンスを返すのか、をひたすら実装していく。

import express from "express";
const app = express();
const port: number = 3000;
app.get("/", (Req: express.Request, res: express.Response) => {
  res.json({ message: "ok" });
  // res.status(500).json({ message: "error"}) // エラーレスポンスはこんな感じ
});
app.listen(port, () => console.log("ok, port =", port));

パスパラメータ

パスを指定する場所で、たとえば:user_idのように、コロンに続けて変数名を指定する。例として、ユーザIDを受け取るような状況を考える。

import express from "express";
const app = express();
const port: number = 3000;
app.get("/:user_id", (req: express.Request, res: express.Response) => {
  res.json({ message: "ok", user_id: req.params.user_id });
});
app.listen(port, () => console.log("ok, port =", port));

このように、req.paramsに続けて受け取った変数名を書くことで、パスを用いて渡された変数の値を取得することができるので、例えば~/1などにアクセスすることができるようになる。

POSTされたJSONの受け取り方

const port: number = 3000;
import express from "express";
const app = express();
import bodyParser from "body-parser";
app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);
app.use(bodyParser.json());
app.post("/:user_id", (req: express.Request, res: express.Response) => {
  res.json({ message: "ok", user_id: req.params.user_id, data: req.body });
});
app.listen(port, () => console.log("ok, port =", port));

ルート

ルートを使うとあるパス配下の処理をまとめて扱うことができる。またルート単位に処理を割り当てて、そのルート配下であればリクエストがくるたびに割り当てた処理を実行させることができる。 例えば、/api/v0云々というパスに対するリクエストに来たら同じ処理をさせる場合は、以下のようなかたちになる。

import express from "express";
const app = express();
const port: number = 3000;

const apiRouter = express.Router();  // ルータを作る
app.use("/api/v0", apiRouter);  // ルータをパスに割り当てる
apiRouter.use(  // このルータで使うミドルウェアを設定する。
  async (
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => {
    // 例えばログインしている場合はユーザ情報を取得するとかその手のことをやる。
    next(); // これを呼ぶと次の関数が実行される、呼ばないと実行されない。
  }
);
apiRouter.get("/", (req: express.Request, res: express.Response) => {
  res.json({ message: "ok" });
});
app.listen(port, () => console.log("ok, port =", port));

なお、このように割り当てる処理のことをミドルウェアと呼ぶ。

JWT

APIサーバでの認証方法のひとつとしてトークンを用いるという方式があり、トークンの仕様のひとつとしてIETFによりRFC7519で定められたJWTがある。

https://datatracker.ietf.org/doc/html/rfc7519

これを使えばどうにかできるだろう。

https://github.com/auth0/node-jsonwebtoken

CORS

APIサーバなので、別のサーバが配信したHTMLからたたかれることを想定しなくてはならないこともあるだろう。

import express from "express";
import cors from "cors";
const app = express();
app.use(cors());

入力値のバリデーション

express-validatorを使えばよさそう。

https://express-validator.github.io/docs/

しめのあいさつ

なにか書き足したほうがよさそうなことを思いついたら順次追記していきます。