# セッション {#sessions}

セッションを使用すると、複数のリクエスト間でユーザーのデータを永続化できます。セッションは、新しいセッションが初期化されたときに、HTTPレスポンスと共に一意のCookieを作成して返すことで機能します。ブラウザは自動的にこのCookieを検出し、将来のリクエストに含めます。これにより、Vaporはリクエストハンドラで特定のユーザーのセッションを自動的に復元できます。

セッションは、WebブラウザにHTMLを直接提供するVaporで構築されたフロントエンドWebアプリケーションに最適です。APIの場合は、リクエスト間でユーザーデータを永続化するために、ステートレスな[トークンベース認証](../security/authentication.md)の使用をお勧めします。

## 設定 {#configuration}

ルートでセッションを使用するには、リクエストが`SessionsMiddleware`を通過する必要があります。これを実現する最も簡単な方法は、このミドルウェアをグローバルに追加することです。Cookieファクトリを宣言した後にこれを追加することをお勧めします。これは、Sessionsが構造体であるため、参照型ではなく値型だからです。値型であるため、`SessionsMiddleware`を使用する前に値を設定する必要があります。

```swift
app.middleware.use(app.sessions.middleware)
```

ルートのサブセットのみがセッションを利用する場合は、代わりに`SessionsMiddleware`をルートグループに追加できます。

```swift
let sessions = app.grouped(app.sessions.middleware)
```

セッションによって生成されるHTTP Cookieは、`app.sessions.configuration`を使用して設定できます。Cookie名を変更し、Cookie値を生成するためのカスタム関数を宣言できます。

```swift
// Cookie名を"foo"に変更します。
app.sessions.configuration.cookieName = "foo"

// Cookie値の作成を設定します。
app.sessions.configuration.cookieFactory = { sessionID in
    .init(string: sessionID.string, isSecure: true)
}

app.middleware.use(app.sessions.middleware)
```

デフォルトでは、VaporはCookie名として`vapor_session`を使用します。

## ドライバー {#drivers}

セッションドライバーは、識別子によってセッションデータの保存と取得を担当します。`SessionDriver`プロトコルに準拠することで、カスタムドライバーを作成できます。

!!! warning
    セッションドライバーは、`app.sessions.middleware`をアプリケーションに追加する_前に_設定する必要があります。

### インメモリ {#in-memory}

Vaporはデフォルトでインメモリセッションを利用します。インメモリセッションは設定が不要で、アプリケーションの起動間で永続化されないため、テストに最適です。インメモリセッションを手動で有効にするには、`.memory`を使用します：

```swift
app.sessions.use(.memory)
```

本番環境での使用例については、データベースを使用してアプリの複数のインスタンス間でセッションを永続化および共有する他のセッションドライバーを確認してください。

### Fluent

Fluentには、アプリケーションのデータベースにセッションデータを保存するサポートが含まれています。このセクションでは、[Fluentを設定](../fluent/overview.md)し、データベースに接続できることを前提としています。最初のステップは、Fluentセッションドライバーを有効にすることです。

```swift
import Fluent

app.sessions.use(.fluent)
```

これにより、アプリケーションのデフォルトデータベースを使用するようにセッションが設定されます。特定のデータベースを指定するには、データベースの識別子を渡します。

```swift
app.sessions.use(.fluent(.sqlite))
```

最後に、`SessionRecord`のマイグレーションをデータベースのマイグレーションに追加します。これにより、`_fluent_sessions`スキーマにセッションデータを保存するためのデータベースが準備されます。

```swift
app.migrations.add(SessionRecord.migration)
```

新しいマイグレーションを追加した後、必ずアプリケーションのマイグレーションを実行してください。セッションはアプリケーションのデータベースに保存されるようになり、再起動間で永続化され、アプリの複数のインスタンス間で共有できます。

### Redis

Redisは、設定されたRedisインスタンスにセッションデータを保存するサポートを提供します。このセクションでは、[Redisを設定](../redis/overview.md)し、Redisインスタンスにコマンドを送信できることを前提としています。

セッションにRedisを使用するには、アプリケーションを設定するときに選択します：

```swift
import Redis

app.sessions.use(.redis)
```

これにより、デフォルトの動作でRedisセッションドライバーを使用するようにセッションが設定されます。

!!! seealso
    RedisとSessionsの詳細については、[Redis &rarr; Sessions](../redis/sessions.md)を参照してください。

## セッションデータ {#session-data}

セッションが設定されたので、リクエスト間でデータを永続化する準備ができました。新しいセッションは、`req.session`にデータが追加されたときに自動的に初期化されます。以下の例のルートハンドラは、動的ルートパラメータを受け入れ、その値を`req.session.data`に追加します。

```swift
app.get("set", ":value") { req -> HTTPStatus in
    req.session.data["name"] = req.parameters.get("value")
    return .ok
}
```

以下のリクエストを使用して、名前Vaporでセッションを初期化します。

```http
GET /set/vapor HTTP/1.1
content-length: 0
```

以下のようなレスポンスを受け取るはずです：

```http
HTTP/1.1 200 OK
content-length: 0
set-cookie: vapor-session=123; Expires=Fri, 10 Apr 2020 21:08:09 GMT; Path=/
```

`req.session`にデータを追加した後、`set-cookie`ヘッダーがレスポンスに自動的に追加されていることに注意してください。このCookieを後続のリクエストに含めることで、セッションデータにアクセスできます。

セッションから名前の値にアクセスするための以下のルートハンドラを追加します。

```swift
app.get("get") { req -> String in
    req.session.data["name"] ?? "n/a"
}
```

前のレスポンスからのCookie値を必ず渡しながら、以下のリクエストを使用してこのルートにアクセスします。

```http
GET /get HTTP/1.1
cookie: vapor-session=123
```

レスポンスで名前Vaporが返されるのが確認できるはずです。必要に応じてセッションからデータを追加または削除できます。セッションデータは、HTTPレスポンスを返す前にセッションドライバーと自動的に同期されます。

セッションを終了するには、`req.session.destroy`を使用します。これにより、セッションドライバーからデータが削除され、セッションCookieが無効になります。

```swift
app.get("del") { req -> HTTPStatus in
    req.session.destroy()
    return .ok
}
```