コンテンツにスキップ

Redis & セッション

Redisはセッションデータ(ユーザー認証情報など)をキャッシュするためのストレージプロバイダーとして機能します。

カスタムのRedisSessionsDelegateが提供されない場合、デフォルトのものが使用されます。

デフォルトの動作

SessionIDの作成

独自のRedisSessionsDelegatemakeNewID()メソッドを実装しない限り、すべてのSessionID値は以下の手順で作成されます:

  1. 32バイトのランダムな文字を生成
  2. その値をbase64エンコード

例:Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

SessionDataの保存

RedisSessionsDelegateのデフォルト実装は、SessionDataCodableを使用してシンプルなJSON文字列値として保存します。

独自のRedisSessionsDelegatemakeRedisKey(for:)メソッドを実装しない限り、SessionDataSessionIDvrs-Vapor Redis Sessions)というプレフィックスを付けたキーでRedisに保存されます。

例:vrs-Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

カスタムデリゲートの登録

Redisへのデータの読み書き方法をカスタマイズするには、独自のRedisSessionsDelegateオブジェクトを以下のように登録します:

import Redis

struct CustomRedisSessionsDelegate: RedisSessionsDelegate {
    // 実装
}

app.sessions.use(.redis(delegate: CustomRedisSessionsDelegate()))

RedisSessionsDelegate

APIドキュメント:RedisSessionsDelegate

このプロトコルに準拠するオブジェクトを使用して、SessionDataがRedisに保存される方法を変更できます。

プロトコルに準拠する型が実装する必要があるメソッドは2つのみです:redis(_:store:with:)redis(_:fetchDataFor:)

セッションデータをRedisに書き込む方法のカスタマイズは、Redisからデータを読み取る方法と本質的に関連しているため、両方とも必須です。

RedisSessionsDelegateハッシュの例

例えば、セッションデータをRedisのハッシュとして保存したい場合、以下のような実装を行います:

func redis<Client: RedisClient>(
    _ client: Client,
    store data: SessionData,
    with key: RedisKey
) -> EventLoopFuture<Void> {
    // 各データフィールドを個別のハッシュフィールドとして保存
    return client.hmset(data.snapshot, in: key)
}
func redis<Client: RedisClient>(
    _ client: Client,
    fetchDataFor key: RedisKey
) -> EventLoopFuture<SessionData?> {
    return client
        .hgetall(from: key)
        .map { hash in
            // hashは[String: RESPValue]なので、値を文字列として
            // アンラップして各値をデータコンテナに保存する必要があります
            return hash.reduce(into: SessionData()) { result, next in
                guard let value = next.value.string else { return }
                result[next.key] = value
            }
        }
}