You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Scotty/Wai设置Cookie?寻求更优雅的实现方式

Hey there! I totally get where you're coming from—dealing with cookies via raw HTTP headers in Scotty can feel pretty low-level and clunky. Let me share some better options to handle this more elegantly:

You mentioned the cookie package only returns fully rendered cookie strings, but it actually has robust parsing utilities to extract key-value pairs from request headers. This is the foundation of clean cookie handling in the Wai/Scotty ecosystem. Here's how to use it effectively:

First, import the required modules:

import Web.Scotty
import Network.HTTP.Types.Header (hCookie)
import Web.Cookie (parseCookies)

Then, in your route handler, extract and parse cookies with minimal boilerplate:

get "/my-route" $ do
  req <- request
  case lookup hCookie (requestHeaders req) of
    Just cookieStr -> do
      let cookies = parseCookies cookieStr
      -- `cookies` is now a [(ByteString, ByteString)] of key-value pairs
      text $ "Cookie value for 'user-id': " <> show (lookup "user-id" cookies)
    Nothing -> text "No cookies found in the request"

For setting cookies, the package's renderSetCookie function handles all the spec-compliant formatting, which you can pair with Scotty's setHeader:

import Web.Cookie (SetCookie(..), renderSetCookie)
import Data.Time.Clock (addUTCTime, getCurrentTime)

get "/set-cookie" $ do
  currentTime <- liftIO getCurrentTime
  let sessionCookie = SetCookie
        { setCookieName = "user-id"
        , setCookieValue = "12345"
        , setCookieExpires = Just $ addUTCTime 86400 currentTime -- Expire in 1 day
        , setCookieDomain = Nothing
        , setCookiePath = Just "/"
        , setCookieSecure = False -- Set to True if using HTTPS
        , setCookieHttpOnly = True -- Helps prevent XSS
        , setCookieSameSite = Nothing
        }
  setHeader "Set-Cookie" $ renderSetCookie sessionCookie
  text "Session cookie set successfully!"

This takes care of all the nitty-gritty details like value escaping and header formatting, so you don't have to reinvent the wheel.

2. Build Reusable Helper Functions

To make your code even cleaner and avoid repeating boilerplate across routes, wrap the cookie logic in custom helper functions tailored to Scotty's ActionM monad:

import Web.Scotty
import Network.HTTP.Types.Header (hCookie, hSetCookie)
import Web.Cookie (parseCookies, SetCookie, renderSetCookie)
import Data.ByteString.Char8 (unpack, pack)

-- Get a cookie value by name (returns Nothing if missing)
getCookie :: String -> ActionM (Maybe String)
getCookie cookieName = do
  req <- request
  let cookieHeader = lookup hCookie (requestHeaders req)
  case cookieHeader of
    Just cookieStr -> do
      let cookies = parseCookies cookieStr
      return $ unpack <$> lookup (pack cookieName) cookies
    Nothing -> return Nothing

-- Set a cookie using the `SetCookie` type from the cookie package
setCookie :: SetCookie -> ActionM ()
setCookie = setHeader hSetCookie . renderSetCookie

Now using cookies in your routes becomes as simple as:

get "/profile" $ do
  userId <- getCookie "user-id"
  case userId of
    Just id -> text $ "Welcome back, user #" <> id
    Nothing -> text "Please log in to view your profile"

This abstraction keeps your route handlers focused on business logic rather than low-level header manipulation.

3. Check Out Scotty-Focused Wrappers (If Available)

While there isn't a massive ecosystem of Scotty-specific cookie libraries, keep an eye out for small community-maintained packages that wrap the cookie package into a more Scotty-native API. These can save you the trouble of writing your own helpers, though the custom helper approach above is straightforward and gives you full control.

Final Takeaway

Don't sleep on the cookie package—it's more powerful than it might appear at first glance. Pairing it with custom helper functions will give you the elegant, maintainable cookie handling you're looking for, without dipping down into raw HTTP header manipulation unless you absolutely need to.

内容的提问来源于stack exchange,提问作者Chris Stryczynski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:32:15