SvelteKitとVaporでSSRした際にCookieがパーセントエンコードされてSessionが動かないのを解決する方法
Last Updated on 2023年8月4日 by lemonade
この記事は、Server-Side SwiftフレームワークVaporとSvelteKitによるSSR(Server-Side Rendering)を使用した際にSvelteKitのSSRでのfetch時にcookieの値がパーセントエンコードされてVaporがそれをsession idが異なると認識するためにsessionが働かなくなるというのを解決するための方法を説明しています。
解決方法
このようなクッキー値をパーセントデコードするミドルウェアを自作します。
import Vapor
import Foundation
struct CookieMiddleware: AsyncMiddleware {
func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response {
guard var cookie = request.cookies["vapor-session"] else {
return try await next.respond(to: request)
}
if let decoded = cookie.string.removingPercentEncoding {
cookie.string = decoded
request.cookies["vapor-session"] = cookie
}
return try await next.respond(to: request)
}
}
configure関数内でsessionミドルウェアを設定する前にこのミドルウェアを設定します。
import NIOSSL
import Fluent
import FluentPostgresDriver
import Vapor
// configures your application
public func configure(_ app: Application) async throws {
// ...
app.middleware.use(CookieMiddleware())
app.middleware.use(app.sessions.middleware)
// ...
}
問題について
特に述べることはないのですが、Cookieのエンコード方法はRFC6525で
To maximize compatibility with user agents, servers that wish to store arbitrary data in a cookie-value SHOULD encode that data, for example, using Base64 [RFC4648].https://datatracker.ietf.org/doc/html/rfc6265
和訳すると
ユーザーエージェントとの互換性を最大限にするために、サーバーが任意のデータをクッキー値に保存したい場合、そのデータを例えばBase64 [RFC4648]を使用してエンコードするべきです。
とされています。base64でエンコードされるのが多いようですが、明確にエンコード方法は定められていません。
SvelteKitではサーバー内でfetchが実行されるとnode-fetchで、クライアント側で実行される際にはwindow.fetchが使用されるようですが、node-fetchではパーセントエンコードされてしまうのかもしれませんが、サーバーにはパーセントエンコードされたCookieが送られ、sessionをうまく動かすことができません。