こんにちは。ぬこすけです。
皆さんは Bot のアクセスに悩まされたことはありますか?
私はあります。
私が個人開発しているサイトでも Bot からガンガンアクセスがきます。
1ページリクエストすると画像や js ファイルなどの追加のリクエストも走るのでやっかいです。
私のサイトは Cloud Run
で動かしていますが、リクエストに比例して料金が加算するようにしているので、 Bot からの余計なリクエストを抑えてお財布に優しくしたいところです。
一方で、 Next.js
のバージョン 12.2 で Middleware
という機能が安定版としてリリースされました。
この Middleware
という機能を使えば、 ユーザーからのリクエストが来た時にページを返却する前にコードを実行することができます。
例えば、ユーザーエージェントを判定してリダイレクトをしたり、Basic認証をかけたり、みたいなことができます。
今回は Middleware
を使ってこの迷惑 Bot たちを追い払います。
やることは簡単です。
-
public
ディレクトリ配下に Bot 用の html ファイルを用意しておく。 - プロジェクトのルート配下に
middleware.js(ts)
を置いて 20 行くらいコード書く。
はい、終わりです。
するとこんな感じでステータスコード 403(Forbidden) で返却することができます。
詳しく説明していきます。
1. public
ディレクトリ配下に Bot 用の html ファイルを用意しておく。
Bot 向けに表示する html ファイルを用意します。
例えば次のような 403.html
を用意して public
配下に置きます。
<html lang='ja'>
<head>
<title>Forbidden</title>
<meta name='robots' content='noindex' />
</head>
<body>
<p>
Forbidden
</p>
</body>
</html>
Bot 相手なので凝った html を用意しなくて大丈夫でしょう。
2. プロジェクトのルート配下に middleware.js(ts)
を置いて 20 行くらいコード書く。
Next.js
ではプロジェクトのルートディレクト直下に middleware.js
( TypeScript なら middleware.ts
)を置くことで Middleware
機能を使うことができます。
次のような middleware.js
を用意しましょう。
import { NextResponse, userAgent } from 'next/server';
// 追い払いたい Bot たち
const uaBlackList = Object.freeze([
'PetalBot',
'SemrushBot',
]);
export function middleware(req) {
const { ua } = userAgent(req);
// robot.txt へのアクセスは除く
if (
uaBlackList.some((blackUa) => ua.indexOf(blackUa) > -1) &&
req.nextUrl.pathname !== '/robots.txt'
) {
req.nextUrl.pathname = '/403.html';
return NextResponse.rewrite(req.nextUrl, { status: 403 });
}
return NextResponse.next();
}
この middleware.js
では予め定義したブラックリストに含まれる Bot からアクセスが来た時は 403.html
を表示し、それ以外の場合は通常通りページを表示します。
あとは本番環境にデプロイして終わりです。
ユーザーエージェントを Bot に偽装してページにアクセスすると次のような画面が表示されます。
[余談] html じゃなくて Next.js
のカスタムエラーページを表示しないの?
余談なので読み飛ばしても大丈夫です。
Next.js
には pages/404.jsx
のようにカスタムエラーページを表示する機能がありますが、これは使いません。
というのも、カスタムエラーページを表示した場合、さらに余計なリクエストが middleware
に来てしまうことがあるから です。
例えば全ページ共通の _document.jsx
に次のような jsx が定義されていたとします。
export default function Document() {
return (
<Html lang='ja'>
<Head>
...
<link rel='icon' href='/images/icons/icon-16x16.png' sizes='16x16' type='image/png' />
...
</Head>
...
</Html>
);
}
この場合、 Bot からアクセスが来て pages/404.jsx
を表示しても、さらに /images/icons/icon-16x16.png
へ追加のリクエストが飛んできます。
できれば、余計な Bot からはリクエストを抑えたいので 403.html
のような静的なファイルを用意しています。
まとめ
-
public
ディレクトリ配下に Bot 用の html ファイルを用意しておく。 - プロジェクトのルート配下に
middleware.js(ts)
を置いて 20 行くらいコード書く。
これだけでサクッと Bot からの余計なアクセスを抑えることができました。
Next.js
で Bot のアクセス対策をしたい時はぜひ参考にしてみてください!