Next.jsが提供するuserAgentでユーザーの情報を取得する

Next.jsには[`userAgent`](https://nextjs.org/docs/app/api-reference/functions/userAgent)を用いて、リクエストからユーザーエージェントを獲得する方法が提供されています。

```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  console.log(ua);
  ...
  return NextResponse.next();
}
```
`Route Handler`や`middleware`の引数の`request`を`next/server`が提供する`userAgent`で囲むとユーザーエージェントについての情報を取得できます。

取得した値からは7種類の情報を読み取れます。いずれも`request.headers.get('user-agent')`の情報を利用して獲得しています。

1つ目は`isBot`です。リクエストが既知のBotによるものかを確認します。
Next.jsのバージョン15.1.0の段階では以下のものを検知します。

`Googlebot`、`Mediapartners-Google`、`AdsBot-Google`、`googleweblight`、`Storebot-Google`、`Google-PageRenderer`、`Google-InspectionTool`、`Bingbot`、`BingPreview`、`Slurp`、`DuckDuckBot`、`baiduspider`、`yandex`、`sogou`、`LinkedInBot`、`bitlybot`、`umblr`、`vkShare`、`quora link preview`、`facebookexternalhit`、`facebookcatalog`、`Twitterbot`、`applebot`、`redditbot`、`Slackbot`、`Discordbot`、`WhatsApp`、`SkypeUriPreview`、`ia_archiver`

`isBot`はNext.jsが独自に実装していまが、それ以外の情報は[ua-parser-js](https://uaparser.dev/)を用いています。

```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // true or false
  console.log(ua.isBot);
  ...
  return NextResponse.next();
}

```

2つ目は`ua`です。`request.headers.get('user-agent')`と同じ情報をそのまま渡します。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
  console.log(ua.ua);
  ...
  return NextResponse.next();
}
```

3つ目は`browser`です。オブジェクトでブラウザ名とバージョン、メジャーバージョンを返します。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: { name: 'Chrome', version: '131.0.0.0', major: '131' }
  console.log(ua.browser);
  ...
  return NextResponse.next();
}
```

4つ目は`device`です。デバイスの情報をベンダーとモデル、種類に分けて提供します。
ベンダーは`Apple`とか`Sony`や`Google`、`Tesla`などの情報です。
種類はゲーム機等を意味する`console`や`iPad`等を意味する`tablet`、`iPhone`や`Galaxy`などを意味する`mobile`等の情報です。PCに値するものはないようです。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: { vendor: 'Apple', model: 'Macintosh', type: undefined }
  console.log(ua.device);
  ...
  return NextResponse.next();
}
```

5つ目は`engine`です。エンジンはレンダリングエンジン名とバージョンを返します。
エンジン名とは`WebKit`や`Gecko`などです。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: { name: 'Blink', version: '131.0.0.0' }
  console.log(ua.engine);
  ...
  return NextResponse.next();
}
```

6つ目は`os`です。osの名前を種類を返します。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: { name: 'Mac OS', version: '10.15.7' }
  console.log(ua.os);
  ...
  return NextResponse.next();
}
```

7つ目は`cpu`です。CPUのアーキテクチャを返します。`architecture`だけをキーに持ちます。`arm64`や`	Intel x86`を使っている場合は`ia32`のように返します。
Apple製品は`arm64`くらいしか対応していないかも知れません(手元にあるiPhone15・M2チップのMacBook Air・Intel MacBookPro・数年前のiPad Proで試しましたところM2チップのMacBook Airだけ動きました)。
```ts
import { NextResponse, userAgent } from 'next/server';

export function middleware(request: Request) {
  const ua = userAgent(request);
  // 例: { architecture: undefined }
  console.log(ua.cpu);
  ...
  return NextResponse.next();
}
```

以上が`userAgent`で確認できることです。内部での依存はありますが、開発に利用するパッケージが他のライブラリに依存することなくユーザーの情報を取得できるのは嬉しいです。

これを用いることで、環境によって異なるサービスを提供することができますが、それは良い行いではありません。できる限り機能をベースに提供する内容を変更しましょう。
詳しくは[MDNのユーザーエージェント文字列を用いたブラウザーの判定](https://developer.mozilla.org/ja/docs/Web/HTTP/Browser_detection_using_the_user_agent)を読んでください。