我将Yesod与serversession-backend-redis集成在一起并尝试运行,这里做个备忘录

为了学习,我尝试了使用Haskell的Web框架Yesod和用于支持会话管理的服务器库serversession进行组合运行。

这次我们使用了stack的模板yesodweb/simple,在这个项目中命名为redissession。

stack new redissession yesodweb/simple

这次我想在Session存储中使用Redis,所以我使用了一个叫做serversession的库。(虽然这个库好像很久没有维护了,但是这次我只是为了看看在Haskell中实现会话操作的例子,所以我不会介意继续使用它。)

首先,在package.yaml文件中添加serversession包的信息。
由于前端使用Yesod,后端使用Redis,因此还需要添加serversession-frontend-yesod和serversession-backend-redis。
另外,由于serversession-backend-redis依赖于hedis包,所以也需要添加它。

dependencies:
(中略)
- serversession == 1.0.1
- serversession-frontend-yesod == 1.0
- serversession-backend-redis == 1.0.3
- hedis < 0.11

由于 serversession-frontend-yesod 和 serversession-backend-redis 不包含在本次使用的 Stackage 的 lts-16.20 解析器中,所以它们也将被添加到 stack.yaml 文件中。
此外,由于包之间的版本依赖关系不匹配,导致出现错误,因此设置 “allow-newer: true” 来忽略版本依赖关系不匹配的问题。
由于本次的目的是先尝试运行,所以这样就可以了。

extra-deps:
- serversession-frontend-yesod-1.0
- serversession-backend-redis-1.0.3

allow-newer: true
import ...()

-- 以下を追記
import Web.ServerSession.Backend.Redis (RedisStorage(..))
import Web.ServerSession.Frontend.Yesod (simpleBackend, setCookieName, setSecureCookies)
import qualified Database.Redis as Redis

(中略)

data App = App 
    { appSettings    :: AppSettings
    , appStatic      :: Static -- ^ Settings for static file serving.
    , appHttpManager :: Manager
    , appLogger      :: Logger
    , appConn        :: Redis.Connection --追加
    }
instance Yesod App where

(中略)

  makeSessionBackend :: App -> IO (Maybe SessionBackend)
  makeSessionBackend = simpleBackend opts . createStorage
    where createStorage appl = RedisStorage (appConn appl) idleTimeoutSec absoluteTimeoutSec
          idleTimeoutSec     = Just $ 60*10
          absoluteTimeoutSec = Just $ 60*30
          opts               = setCookieName "REDISSESSION_ID"
                             . setSecureCookies False
import qualified Database.Redis as Redis

makeFoundation :: AppSettings -> IO App 
makeFoundation appSettings = do
    -- Some basic initializations: HTTP connection manager, logger, and static
    -- subsite.
    appHttpManager <- getGlobalManager
    appLogger <- newStdoutLoggerSet defaultBufSize >>= makeYesodLogger
    appStatic <-
        (if appMutableStatic appSettings then staticDevel else static)
        (appStaticDir appSettings)
    appConn <- Redis.connect Redis.defaultConnectInfo  -- ここを追記                                                                                                                                                                                       

    -- Return the foundation
    return App {..}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE QuasiQuotes #-} --追加

import Web.ServerSession.Frontend.Yesod (forceInvalidate, ForceInvalidate(..))
import Import
import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3)
import Text.Julius (RawJS (..))

import Web.ServerSession.Frontend.Yesod (forceInvalidate, ForceInvalidate(..)) 
getHomeR :: Handler Html
getHomeR = do
    sess <- getSession
    forceInvalidate CurrentSessionId -- これを呼ぶとセッションIDが再採番される
    defaultLayout
        [whamlet|
            <form method=post>
                <input type=text name=key>
                <input type=text name=val>
                <input type=submit>
            <h1>#{show sess}
        |]  

postHomeR :: Handler ()
postHomeR = do
    (key, mval) <- runInputPost $ (,) <$> ireq textField "key" <*> iopt textField "val"
    case mval of
        Nothing -> deleteSession key 
        Just val -> setSession key val 
    liftIO $ print (key, mval)
    redirect HomeR

我会试着动一下。

我会启动Redis。

$ redis-server

开始启动Web服务器

$ stack exec -- yesod devel

由于Web服务器已经启动,现在我们可以在Web浏览器中访问localhost:3000。

スクリーンショット 2021-01-06 23.37.17.png

在Set-Cookie头部中,有一个名为”REDISSESSION_ID”的字段。看起来运行良好。
接下来,我们尝试将数据保存在会话存储中。
我们将指定键为”hoge”,值为”fuga”。

スクリーンショット 2021-01-06 23.37.33.png

Session信息已在屏幕上显示。看起来运行正常。
(由于调用了”forceInvalidate CurrentSessionId”,因此”SetCookie”头部的”REDISSESSION_ID”值已更改,但在此时刻实际上并不需要。)

スクリーンショット 2021-01-06 23.38.03.png

在redis-cli中,我们可以预览存储在Redis中的数据。

スクリーンショット 2021-01-06 22.52.08.png

在浏览器中输入的数据已经被正确保存。

广告
将在 10 秒后关闭
bannerAds