LoginSignup
2
1

More than 1 year has passed since last update.

【Node.js】Expressで存在しないパスにアクセスした時の404エラーハンドリング【Inversify Express Utils】

Last updated at Posted at 2022-09-29

初めに

Expressのエラーハンドラは存在しないパスにアクセスした時のエラー(404)はハンドリングしてくれません。
じゃあどうしたらいいか? を調べたのでここにまとめます。

サンプルファイル

ここにExpressを使ったserver.tsファイルを用意します。
ポート3000でサーバを起動し、/usersというルータのみ用意しています。

import express from "express"
const app: express.Express = express()

// サーバ起動
app.listen(3000, () => {
  console.log("Start on port 3000.")
})

// ユーザ一覧
app.get("/user", (req: express.Request, res: express.Response) => {
  res.send("OK")
})

エラーハンドラを定義してみる

Expressでデフォルトのエラーハンドラをミドルウェアに用意するなら一番下に以下を追記するといいです。
参考: Express エラー処理

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

(↑引用なのでjsです)

しかしこれだと、存在しないパスにアクセスしたときの404エラーはキャッチしてくれないようです。
試しにサーバを起動して、適当なパスにアクセスしてみます。
エラーハンドラを通っていれば 「Something broke!」 と表示されるはずですが、結果はそうではありません。

image.png

404をハンドリングするには

こういう時は、ルーティングの一番最後になんでも通すルーターを用意して、
そこにアクセスが来たら404ページを表示するなどしてハンドリングしたらいいみたいです。

// 404ハンドラー
app.all("*", (req, res) => {
  res.send("404!")
})

(↑引用なのでjsです)

もう一度同じページにアクセスしてみると、きちんとハンドリングできたのがわかります。
image.png

まとめ

まとめると以下のファイルになります。

import express from "express"
const app: express.Express = express()

// サーバ起動
app.listen(3000, () => {
  console.log("Start on port 3000.")
})

// ユーザ一覧
app.get("/user", (req: express.Request, res: express.Response) => {
  res.send("OK")
})

// 404ハンドラー
app.all("*", (req, res) => {
  res.send("404!")
})

// エラーハンドラ
app.use(
  (
    err: Error,
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => {
    console.error(err.stack)
    res.send("Something broke!")
  }
)

これで存在しないpathにアクセスした時の404エラーハンドリングができるようになりました。

おまけ Inversify Express Utilsを使ったケース

普段はDIライブラリのInversify Express Utilsを使っています。
この場合は上記のやり方でルーティングを定義すると、@controllerで定義したルーティングよりも app.all() で定義したルーティングが優先されてしまったりでうまく動きません。
そういう時はこちらのISSUEを参考に以下のように書いてください。

@controller("*")
class NotFoundController {
  @httpGet("/")
  public async index() {
    return Promise.resolve("not found!");
  }
}

@controller("/")
class HomeController {

  @httpGet("/")
  public index() {
    return Promise.resolve("home!");
  }
}

const container = new Container();
const server = new InversifyExpressServer(container);
const app = server.build();

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

ポイントは @controller("*")一番先頭に定義することです。
ミドルウェアを使ったときは一番最後に定義しましたが、inversify-express-utilsを使うときはなのでお気をつけください。

参考にさせていただきました

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1