Vai al contenuto

Redis & Sessioni

Redis può fungere da provider di archiviazione per il caching dei dati di sessione come le credenziali degli utenti.

Se non viene fornito un RedisSessionsDelegate personalizzato, sarà utilizzato quello di default.

Comportamento di Default

Creazione di SessionID

A meno che non implementi il metodo makeNewID() nel tuo RedisSessionsDelegate personale, tutti i valori SessionID saranno creati facendo quanto segue:

  1. Generare 32 byte di caratteri casuali
  2. Codificare il valore in base64

Per esempio: Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

Archiviazione di SessionData

L'implementazione di default di RedisSessionsDelegate salverà SessionData come una semplice stringa JSON usando Codable.

A meno che non implementi il metodo makeRedisKey(for:) nel tuo RedisSessionsDelegate personale, SessionData sarà salvato in Redis con una chiave che precede il SessionID con vrs- (Vapor Redis Sessions)

Per esempio: vrs-Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

Registrare un Delegato Modificato

Per modificare il modo in cui i dati vengono letti e scritti su Redis, registra il tuo oggetto RedisSessionsDelegate come segue:

import Redis

struct CustomRedisSessionsDelegate: RedisSessionsDelegate {
    // implementazione
}

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

RedisSessionsDelegate

Documentazione dell'API: RedisSessionsDelegate

Un oggetto che è conforme a questo protocollo può essere usato per cambiare come SessionData è salvato in Redis.

Viene richiesto di implementare solo due metodi a un tipo conforme al protocollo: redis(_:store:with:) e redis(_:fetchDataFor:).

Entrambi sono necessari, in quanto il modo in cui tu personalizzi la scrittura dei dati di sessione su Redis è intrinsecamente legato a come deve essere letto da Redis.

Esempio di Hash di RedisSessionsDelegate

Per esempio, se vuoi salvare i dati di sessione come un Hash in Redis, dovresti implementare qualcosa simile a quanto segue:

func redis<Client: RedisClient>(
    _ client: Client,
    store data: SessionData,
    with key: RedisKey
) -> EventLoopFuture<Void> {
    // salva ogni campo dei dati come un campo hash separato
    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] quindi dobbiamo provare e spacchettare il
            // valore come una stringa e salvare ogni valore nel container dei dati
            return hash.reduce(into: SessionData()) { result, next in
                guard let value = next.value.string else { return }
                result[next.key] = value
            }
        }
}