diff --git a/Yesod/Core.hs b/Yesod/Core.hs
index a231d784..a81f01c8 100644
--- a/Yesod/Core.hs
+++ b/Yesod/Core.hs
@@ -46,7 +46,6 @@ import Text.Hamlet
import Text.Cassius
import Text.Julius
import Text.Blaze (preEscapedLazyText, (!), customAttribute, textTag, toValue)
-import qualified Data.Text as T
import qualified Text.Blaze.Html5 as TBH
import Data.Text.Lazy.Builder (toLazyText)
import Data.Text.Lazy.Encoding (encodeUtf8)
@@ -56,11 +55,11 @@ import Web.Cookie (parseCookies)
import qualified Data.Map as Map
import Data.Time
import Network.HTTP.Types (encodePath)
-import qualified Network.HTTP.Types as H
import qualified Data.Text as TS
import Data.Text (Text)
import qualified Data.Text.Encoding as TE
-import Blaze.ByteString.Builder (Builder, fromByteString, toByteString)
+import Blaze.ByteString.Builder (Builder, toByteString)
+import Blaze.ByteString.Builder.Char.Utf8 (fromText)
import Data.List (foldl')
#if GHC7
@@ -104,7 +103,7 @@ class RenderRoute (Route a) => Yesod a where
--
-- * You do not use any features that require absolute URLs, such as Atom
-- feeds and XML sitemaps.
- approot :: a -> H.Ascii
+ approot :: a -> Text
-- | The encryption key to be used for encrypting client sessions.
-- Returning 'Nothing' disables sessions.
@@ -215,10 +214,10 @@ class RenderRoute (Route a) => Yesod a where
-- file, whereas a 'Just' 'Right' gives the type-safe URL. The former is
-- necessary when you are serving the content outside the context of a
-- Yesod application, such as via memcached.
- addStaticContent :: String -- ^ filename extension
- -> String -- ^ mime-type
+ addStaticContent :: Text -- ^ filename extension
+ -> Text -- ^ mime-type
-> L.ByteString -- ^ content
- -> GHandler sub a (Maybe (Either String (Route a, [(String, String)])))
+ -> GHandler sub a (Maybe (Either Text (Route a, [(Text, Text)])))
addStaticContent _ _ _ = return Nothing
-- | Whether or not to tie a session to a specific IP address. Defaults to
@@ -292,7 +291,7 @@ defaultYesodRunner s master toMasterRoute mkey murl handler req = do
hs'' = map (headerToPair getExpires) hs'
hs''' = ("Content-Type", ct) : hs''
-data AuthResult = Authorized | AuthenticationRequired | Unauthorized String
+data AuthResult = Authorized | AuthenticationRequired | Unauthorized Text
deriving (Eq, Show, Read)
-- | A type-safe, concise method of creating breadcrumbs for pages. For each
@@ -408,6 +407,7 @@ widgetToPageContent (GWidget w) = do
let title = maybe mempty unTitle mTitle
let scripts = runUniqueList scripts'
let stylesheets = runUniqueList stylesheets'
+ -- FIXME check size of cassius/julius template
let cssToHtml = preEscapedLazyText . renderCss
celper :: Cassius url -> Hamlet url
celper = fmap cssToHtml
@@ -415,8 +415,7 @@ widgetToPageContent (GWidget w) = do
jelper :: Julius url -> Hamlet url
jelper = fmap jsToHtml
- renderFIXME <- getUrlRenderParams
- let render a b = renderFIXME a $ map (TS.pack *** TS.pack) b
+ render <- getUrlRenderParams
let renderLoc x =
case x of
Nothing -> Nothing
@@ -441,9 +440,13 @@ widgetToPageContent (GWidget w) = do
let renderLoc' render' (Local url) = render' url []
renderLoc' _ (Remote s) = s
let mkScriptTag (Script loc attrs) render' =
- foldl' addAttr TBH.script (("src", T.pack $ renderLoc' render' loc) : attrs) $ return ()
+ foldl' addAttr TBH.script (("src", renderLoc' render' loc) : attrs) $ return ()
let mkLinkTag (Stylesheet loc attrs) render' =
- foldl' addAttr TBH.link (("rel", "stylesheet") : ("href", T.pack $ renderLoc' render' loc) : attrs)
+ foldl' addAttr TBH.link
+ ( ("rel", "stylesheet")
+ : ("href", renderLoc' render' loc)
+ : attrs
+ )
let head'' =
#if GHC7
[hamlet|
@@ -475,11 +478,11 @@ yesodRender :: Yesod y
=> y
-> Route y
-> [(Text, Text)]
- -> String -- FIXME
+ -> Text
yesodRender y u qs =
- S8.unpack $ toByteString $
+ TE.decodeUtf8 $ toByteString $
fromMaybe
- (joinPath y (fromByteString $ approot y) ps
+ (joinPath y (fromText $ approot y) ps
$ qs ++ qs')
(urlRenderOverride y u)
where
diff --git a/Yesod/Handler.hs b/Yesod/Handler.hs
index 0d547cde..e62acf1f 100644
--- a/Yesod/Handler.hs
+++ b/Yesod/Handler.hs
@@ -41,6 +41,7 @@ module Yesod.Handler
, redirect
, redirectParams
, redirectString
+ , redirectText
, redirectToPost
-- ** Errors
, notFound
@@ -124,6 +125,12 @@ import qualified Network.HTTP.Types as H
import Control.Failure (Failure (failure))
import Text.Hamlet
+import Text.Blaze (preEscapedText)
+import qualified Text.Blaze.Renderer.Text
+import qualified Data.Text as T
+import Data.Text.Encoding (encodeUtf8, decodeUtf8With)
+import Data.Text.Encoding.Error (lenientDecode)
+import qualified Data.Text.Lazy as TL
import Control.Monad.IO.Control (MonadControlIO)
import Control.Monad.Trans.Control (MonadTransControl, liftControl, control)
@@ -144,7 +151,6 @@ import qualified Data.ByteString.Char8 as S8
import Data.CaseInsensitive (CI)
import Blaze.ByteString.Builder (toByteString)
import Data.Text (Text)
-import qualified Data.Text as TS
-- | The type-safe URLs associated with a site argument.
type family Route a
@@ -157,7 +163,7 @@ data HandlerData sub master = HandlerData
, handlerSub :: sub
, handlerMaster :: master
, handlerRoute :: Maybe (Route sub)
- , handlerRender :: (Route master -> [(Text, Text)] -> String) -- FIXME replace output String with Ascii
+ , handlerRender :: (Route master -> [(Text, Text)] -> Text)
, handlerToMaster :: Route sub -> Route master
}
@@ -251,7 +257,7 @@ type GHInner s m monad = -- FIXME collapse the stack
monad
))))
-type SessionMap = Map.Map String String
+type SessionMap = Map.Map Text Text
type Endo a = a -> a
@@ -274,13 +280,13 @@ data YesodAppResult
data HandlerContents =
HCContent H.Status ChooseRep
| HCError ErrorResponse
- | HCSendFile ContentType FilePath
- | HCRedirect RedirectType H.Ascii
- | HCCreated H.Ascii
+ | HCSendFile ContentType FilePath -- FIXME replace FilePath with opaque type from system-filepath?
+ | HCRedirect RedirectType Text
+ | HCCreated Text
| HCWai W.Response
instance Error HandlerContents where
- strMsg = HCError . InternalError
+ strMsg = HCError . InternalError . T.pack
instance Monad monad => Failure ErrorResponse (GGHandler sub master monad) where
failure = GHandler . lift . throwError . HCError
@@ -301,9 +307,10 @@ rbHelper req =
(map fix1 *** map fix2) <$> iter
where
iter = NWP.parseRequestBody NWP.lbsSink req
- fix1 = bsToChars *** bsToChars
+ fix1 = go *** go
fix2 (x, NWP.FileInfo a b c) =
- (bsToChars x, FileInfo (bsToChars a) (bsToChars b) c)
+ (go x, FileInfo (go a) (go b) c)
+ go = decodeUtf8With lenientDecode
-- | Get the sub application argument.
getYesodSub :: Monad m => GGHandler sub master m sub
@@ -314,7 +321,7 @@ getYesod :: Monad m => GGHandler sub master m master
getYesod = handlerMaster `liftM` GHandler ask
-- | Get the URL rendering function.
-getUrlRender :: Monad m => GGHandler sub master m (Route master -> String)
+getUrlRender :: Monad m => GGHandler sub master m (Route master -> Text)
getUrlRender = do
x <- handlerRender `liftM` GHandler ask
return $ flip x []
@@ -322,7 +329,7 @@ getUrlRender = do
-- | The URL rendering function with query-string parameters.
getUrlRenderParams
:: Monad m
- => GGHandler sub master m (Route master -> [(Text, Text)] -> String)
+ => GGHandler sub master m (Route master -> [(Text, Text)] -> Text)
getUrlRenderParams = handlerRender `liftM` GHandler ask
-- | Get the route requested by the user. If this is a 404 response- where the
@@ -339,7 +346,7 @@ getRouteToMaster = handlerToMaster `liftM` GHandler ask
-- 'GHandler' into an 'W.Application'. Should not be needed by users.
runHandler :: HasReps c
=> GHandler sub master c
- -> (Route master -> [(Text, Text)] -> String)
+ -> (Route master -> [(Text, Text)] -> Text)
-> Maybe (Route sub)
-> (Route sub -> Route master)
-> master
@@ -350,7 +357,7 @@ runHandler handler mrender sroute tomr ma sa =
let toErrorHandler e =
case fromException e of
Just x -> x
- Nothing -> InternalError $ show e
+ Nothing -> InternalError $ T.pack $ show e
let hd = HandlerData
{ handlerRequest = rr
, handlerSub = sa
@@ -384,7 +391,7 @@ runHandler handler mrender sroute tomr ma sa =
return $ YARPlain status (headers []) ct c finalSession
HCError e -> handleError e
HCRedirect rt loc -> do
- let hs = Header "Location" loc : headers []
+ let hs = Header "Location" (encodeUtf8 loc) : headers []
return $ YARPlain
(getRedirectStatus rt) hs typePlain emptyContent
finalSession
@@ -392,7 +399,7 @@ runHandler handler mrender sroute tomr ma sa =
(sendFile' ct fp)
(handleError . toErrorHandler)
HCCreated loc -> do
- let hs = Header "Location" loc : headers []
+ let hs = Header "Location" (encodeUtf8 loc) : headers []
return $ YARPlain
H.status201
hs
@@ -427,13 +434,15 @@ redirectParams :: Monad mo
-> GGHandler sub master mo a
redirectParams rt url params = do
r <- getUrlRenderParams
- redirectString rt $ S8.pack $ r url params
+ redirectString rt $ r url params
-- | Redirect to the given URL.
-redirectString :: Monad mo => RedirectType -> H.Ascii -> GGHandler sub master mo a
-redirectString rt = GHandler . lift . throwError . HCRedirect rt
+redirectString, redirectText :: Monad mo => RedirectType -> Text -> GGHandler sub master mo a
+redirectText rt = GHandler . lift . throwError . HCRedirect rt
+redirectString = redirectText
+{-# DEPRECATED redirectString "Use redirectText instead" #-}
-ultDestKey :: String
+ultDestKey :: Text
ultDestKey = "_ULT"
-- | Sets the ultimate destination variable to the given route.
@@ -446,7 +455,7 @@ setUltDest dest = do
setUltDestString $ render dest
-- | Same as 'setUltDest', but use the given string.
-setUltDestString :: Monad mo => String -> GGHandler sub master mo ()
+setUltDestString :: Monad mo => Text -> GGHandler sub master mo ()
setUltDestString = setSession ultDestKey
-- | Same as 'setUltDest', but uses the current page.
@@ -462,8 +471,7 @@ setUltDest' = do
tm <- getRouteToMaster
gets' <- reqGetParams `liftM` handlerRequest `liftM` GHandler ask
render <- getUrlRenderParams
- let renderFIXME a b = render a $ map (TS.pack *** TS.pack) b
- setUltDestString $ renderFIXME (tm r) gets'
+ setUltDestString $ render (tm r) gets'
-- | Redirect to the ultimate destination in the user's session. Clear the
-- value from the session.
@@ -476,16 +484,16 @@ redirectUltDest :: Monad mo
redirectUltDest rt def = do
mdest <- lookupSession ultDestKey
deleteSession ultDestKey
- maybe (redirect rt def) (redirectString rt . S8.pack) mdest
+ maybe (redirect rt def) (redirectText rt) mdest
-msgKey :: String
+msgKey :: Text
msgKey = "_MSG"
-- | Sets a message in the user's session.
--
-- See 'getMessage'.
setMessage :: Monad mo => Html -> GGHandler sub master mo ()
-setMessage = setSession msgKey . lbsToChars . renderHtml
+setMessage = setSession msgKey . T.concat . TL.toChunks . Text.Blaze.Renderer.Text.renderHtml
-- | Gets the message in the user's session, if available, and then clears the
-- variable.
@@ -493,7 +501,7 @@ setMessage = setSession msgKey . lbsToChars . renderHtml
-- See 'setMessage'.
getMessage :: Monad mo => GGHandler sub master mo (Maybe Html)
getMessage = do
- mmsg <- liftM (fmap preEscapedString) $ lookupSession msgKey
+ mmsg <- liftM (fmap preEscapedText) $ lookupSession msgKey
deleteSession msgKey
return mmsg
@@ -521,7 +529,7 @@ sendResponseStatus s = GHandler . lift . throwError . HCContent s
sendResponseCreated :: Monad mo => Route m -> GGHandler s m mo a
sendResponseCreated url = do
r <- getUrlRender
- GHandler $ lift $ throwError $ HCCreated $ S8.pack $ r url
+ GHandler $ lift $ throwError $ HCCreated $ r url
-- | Send a 'W.Response'. Please note: this function is rarely
-- necessary, and will /disregard/ any changes to response headers and session
@@ -542,11 +550,11 @@ badMethod = do
failure $ BadMethod $ W.requestMethod w
-- | Return a 403 permission denied page.
-permissionDenied :: Failure ErrorResponse m => String -> m a
+permissionDenied :: Failure ErrorResponse m => Text -> m a
permissionDenied = failure . PermissionDenied
-- | Return a 400 invalid arguments page.
-invalidArgs :: Failure ErrorResponse m => [String] -> m a
+invalidArgs :: Failure ErrorResponse m => [Text] -> m a
invalidArgs = failure . InvalidArgs
------- Headers
@@ -564,8 +572,8 @@ deleteCookie = addHeader . DeleteCookie
-- | Set the language in the user session. Will show up in 'languages' on the
-- next request.
-setLanguage :: Monad mo => String -> GGHandler sub master mo ()
-setLanguage = setSession $ S8.unpack langKey
+setLanguage :: Monad mo => Text -> GGHandler sub master mo ()
+setLanguage = setSession langKey
-- | Set an arbitrary response header.
setHeader :: Monad mo
@@ -601,13 +609,13 @@ expiresAt = setHeader "Expires" . S8.pack . formatRFC1123
-- and hashed cookie on the client. This ensures that all data is secure and
-- not tampered with.
setSession :: Monad mo
- => String -- ^ key
- -> String -- ^ value
+ => Text -- ^ key
+ -> Text -- ^ value
-> GGHandler sub master mo ()
setSession k = GHandler . lift . lift . lift . modify . modSession . Map.insert k
-- | Unsets a session variable. See 'setSession'.
-deleteSession :: Monad mo => String -> GGHandler sub master mo ()
+deleteSession :: Monad mo => Text -> GGHandler sub master mo ()
deleteSession = GHandler . lift . lift . lift . modify . modSession . Map.delete
modSession :: (SessionMap -> SessionMap) -> GHState -> GHState
@@ -640,7 +648,7 @@ localNoCurrent =
GHandler . local (\hd -> hd { handlerRoute = Nothing }) . unGHandler
-- | Lookup for session data.
-lookupSession :: Monad mo => ParamName -> GGHandler s m mo (Maybe ParamValue)
+lookupSession :: Monad mo => Text -> GGHandler s m mo (Maybe Text)
lookupSession n = GHandler $ do
m <- liftM ghsSession $ lift $ lift $ lift get
return $ Map.lookup n m
@@ -653,7 +661,7 @@ handlerToYAR :: (HasReps a, HasReps b)
=> m -- ^ master site foundation
-> s -- ^ sub site foundation
-> (Route s -> Route m)
- -> (Route m -> [(Text, Text)] -> String) -- ^ url render FIXME
+ -> (Route m -> [(Text, Text)] -> Text)
-> (ErrorResponse -> GHandler s m a)
-> Request
-> Maybe (Route s)
@@ -782,8 +790,7 @@ hamletToContent :: Monad mo
=> Hamlet (Route master) -> GGHandler sub master mo Content
hamletToContent h = do
render <- getUrlRenderParams
- let renderFIXME a b = render a $ map (TS.pack *** TS.pack) b
- return $ toContent $ h renderFIXME
+ return $ toContent $ h render
-- | Wraps the 'Content' generated by 'hamletToContent' in a 'RepHtml'.
hamletToRepHtml :: Monad mo
diff --git a/Yesod/Internal.hs b/Yesod/Internal.hs
index dd04b4a2..ab43a17f 100644
--- a/Yesod/Internal.hs
+++ b/Yesod/Internal.hs
@@ -41,6 +41,7 @@ import Data.List (nub)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
+import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Encoding.Error as T
@@ -54,6 +55,7 @@ import Control.Exception (Exception)
import qualified Network.HTTP.Types as H
import qualified Network.HTTP.Types as A
import Data.CaseInsensitive (CI)
+import Data.String (IsString)
#if GHC7
#define HAMLET hamlet
@@ -65,9 +67,9 @@ import Data.CaseInsensitive (CI)
-- from 'SpecialResponse' in that they allow for custom error pages.
data ErrorResponse =
NotFound
- | InternalError String
- | InvalidArgs [String]
- | PermissionDenied String
+ | InternalError Text
+ | InvalidArgs [Text]
+ | PermissionDenied Text
| BadMethod H.Method
deriving (Show, Eq, Typeable)
instance Exception ErrorResponse
@@ -80,10 +82,10 @@ data Header =
| Header (CI A.Ascii) A.Ascii
deriving (Eq, Show)
-langKey :: A.Ascii
+langKey :: IsString a => a
langKey = "_LANG"
-data Location url = Local url | Remote String -- FIXME Text
+data Location url = Local url | Remote Text
deriving (Show, Eq)
locationToHamlet :: Location url -> Hamlet url
locationToHamlet (Local url) = [HAMLET|\@{url}
@@ -111,6 +113,7 @@ newtype Head url = Head (Hamlet url)
newtype Body url = Body (Hamlet url)
deriving Monoid
+-- FIXME remove these functions
lbsToChars :: L.ByteString -> String
lbsToChars = LT.unpack . LT.decodeUtf8With T.lenientDecode
@@ -120,10 +123,10 @@ bsToChars = T.unpack . T.decodeUtf8With T.lenientDecode
charsToBs :: String -> S.ByteString
charsToBs = T.encodeUtf8 . T.pack
-nonceKey :: String
+nonceKey :: IsString a => a
nonceKey = "_NONCE"
-sessionName :: A.Ascii
+sessionName :: IsString a => a
sessionName = "_SESSION"
data GWData a = GWData
diff --git a/Yesod/Internal/Dispatch.hs b/Yesod/Internal/Dispatch.hs
index 4c581ccb..f8f073e8 100644
--- a/Yesod/Internal/Dispatch.hs
+++ b/Yesod/Internal/Dispatch.hs
@@ -24,6 +24,7 @@ import Data.Text (Text)
import Data.Monoid (mappend)
import qualified Blaze.ByteString.Builder
import qualified Blaze.ByteString.Builder.Char8
+import Blaze.ByteString.Builder.Char.Utf8 (fromText)
import qualified Data.ByteString.Char8 as S8
{-|
@@ -86,7 +87,7 @@ sendRedirect y segments' env =
, ("Location", Blaze.ByteString.Builder.toByteString dest')
] "Redirecting"
where
- dest = joinPath y (Blaze.ByteString.Builder.fromByteString $ approot y) segments' []
+ dest = joinPath y (fromText $ approot y) segments' []
dest' =
if S.null (W.rawQueryString env)
then dest
diff --git a/Yesod/Internal/Request.hs b/Yesod/Internal/Request.hs
index 62a14490..183b5cb3 100644
--- a/Yesod/Internal/Request.hs
+++ b/Yesod/Internal/Request.hs
@@ -4,34 +4,37 @@ module Yesod.Internal.Request
) where
import Yesod.Request
-import Control.Arrow (first, (***))
+import Control.Arrow (first, second)
import qualified Network.Wai.Parse as NWP
import Yesod.Internal
import qualified Network.Wai as W
import System.Random (randomR, newStdGen)
-import Web.Cookie (parseCookies)
+import Web.Cookie (parseCookiesText)
import Data.Monoid (mempty)
import qualified Data.ByteString.Char8 as S8
+import Data.Text (Text, pack)
+import Network.HTTP.Types (queryToQueryText)
+import Control.Monad (join)
+import Data.Maybe (fromMaybe)
parseWaiRequest :: W.Request
- -> [(String, String)] -- ^ session
+ -> [(Text, Text)] -- ^ session
-> Maybe a
-> IO Request
parseWaiRequest env session' key' = do
- let gets' = map (bsToChars *** maybe "" bsToChars)
- $ W.queryString env
+ let gets' = queryToQueryText $ W.queryString env
let reqCookie = maybe mempty id $ lookup "Cookie"
$ W.requestHeaders env
- cookies' = parseCookies reqCookie
+ cookies' = parseCookiesText reqCookie
acceptLang = lookup "Accept-Language" $ W.requestHeaders env
- langs = map S8.unpack $ maybe [] NWP.parseHttpAccept acceptLang
- langs' = case lookup (S8.unpack langKey) session' of
+ langs = map (pack . S8.unpack) $ maybe [] NWP.parseHttpAccept acceptLang
+ langs' = case lookup langKey session' of
Nothing -> langs
Just x -> x : langs
langs'' = case lookup langKey cookies' of
Nothing -> langs'
- Just x -> S8.unpack x : langs'
- langs''' = case lookup (S8.unpack langKey) gets' of
+ Just x -> x : langs'
+ langs''' = case join $ lookup langKey gets' of
Nothing -> langs''
Just x -> x : langs''
nonce <- case (key', lookup nonceKey session') of
@@ -39,8 +42,9 @@ parseWaiRequest env session' key' = do
(_, Just x) -> return $ Just x
(_, Nothing) -> do
g <- newStdGen
- return $ Just $ fst $ randomString 10 g
- return $ Request gets' cookies' env langs''' nonce
+ return $ Just $ pack $ fst $ randomString 10 g
+ let gets'' = map (second $ fromMaybe "") gets'
+ return $ Request gets'' cookies' env langs''' nonce
where
randomString len =
first (map toChar) . sequence' (replicate len (randomR (0, 61)))
diff --git a/Yesod/Internal/Session.hs b/Yesod/Internal/Session.hs
index cb87d96c..7e840136 100644
--- a/Yesod/Internal/Session.hs
+++ b/Yesod/Internal/Session.hs
@@ -8,11 +8,13 @@ import Data.Serialize
import Data.Time
import Data.ByteString (ByteString)
import Control.Monad (guard)
+import Data.Text (Text, pack, unpack)
+import Control.Arrow ((***))
encodeSession :: CS.Key
-> UTCTime -- ^ expire time
-> ByteString -- ^ remote host
- -> [(String, String)] -- ^ session
+ -> [(Text, Text)] -- ^ session
-> ByteString -- ^ cookie value
encodeSession key expire rhost session' =
CS.encrypt key $ encode $ SessionCookie expire rhost session'
@@ -21,7 +23,7 @@ decodeSession :: CS.Key
-> UTCTime -- ^ current time
-> ByteString -- ^ remote host field
-> ByteString -- ^ cookie value
- -> Maybe [(String, String)]
+ -> Maybe [(Text, Text)]
decodeSession key now rhost encrypted = do
decrypted <- CS.decrypt key encrypted
SessionCookie expire rhost' session' <-
@@ -30,14 +32,14 @@ decodeSession key now rhost encrypted = do
guard $ rhost' == rhost
return session'
-data SessionCookie = SessionCookie UTCTime ByteString [(String, String)]
+data SessionCookie = SessionCookie UTCTime ByteString [(Text, Text)]
deriving (Show, Read)
instance Serialize SessionCookie where
- put (SessionCookie a b c) = putTime a >> put b >> put c
+ put (SessionCookie a b c) = putTime a >> put b >> put (map (unpack *** unpack) c)
get = do
a <- getTime
b <- get
- c <- get
+ c <- map (pack *** pack) `fmap` get
return $ SessionCookie a b c
putTime :: Putter UTCTime
diff --git a/Yesod/Request.hs b/Yesod/Request.hs
index 33b4c768..ce257946 100644
--- a/Yesod/Request.hs
+++ b/Yesod/Request.hs
@@ -31,10 +31,6 @@ module Yesod.Request
, lookupPostParams
, lookupCookies
, lookupFiles
- -- * Parameter type synonyms
- , ParamName
- , ParamValue
- , ParamError
) where
import qualified Network.Wai as W
@@ -43,11 +39,7 @@ import Control.Monad.IO.Class
import Control.Monad (liftM)
import Control.Monad.Instances () -- I'm missing the instance Monad ((->) r
import Data.Maybe (listToMaybe)
-import qualified Network.HTTP.Types as A
-
-type ParamName = String
-type ParamValue = String
-type ParamError = String
+import Data.Text (Text)
-- FIXME perhaps remove RequestReader typeclass, include Request datatype in Handler
@@ -70,7 +62,7 @@ class Monad m => RequestReader m where
-- * Accept-Language HTTP header.
--
-- This is handled by parseWaiRequest (not exposed).
-languages :: RequestReader m => m [String]
+languages :: RequestReader m => m [Text]
languages = reqLangs `liftM` getRequest
-- | Get the request\'s 'W.Request' value.
@@ -79,74 +71,74 @@ waiRequest = reqWaiRequest `liftM` getRequest
-- | A tuple containing both the POST parameters and submitted files.
type RequestBodyContents =
- ( [(ParamName, ParamValue)]
- , [(ParamName, FileInfo)]
+ ( [(Text, Text)]
+ , [(Text, FileInfo)]
)
data FileInfo = FileInfo
- { fileName :: String
- , fileContentType :: String
+ { fileName :: Text
+ , fileContentType :: Text
, fileContent :: BL.ByteString
}
deriving (Eq, Show)
-- | The parsed request information.
data Request = Request
- { reqGetParams :: [(ParamName, ParamValue)]
- , reqCookies :: [(A.Ascii, A.Ascii)]
+ { reqGetParams :: [(Text, Text)]
+ , reqCookies :: [(Text, Text)]
, reqWaiRequest :: W.Request
-- | Languages which the client supports.
- , reqLangs :: [String]
+ , reqLangs :: [Text]
-- | A random, session-specific nonce used to prevent CSRF attacks.
- , reqNonce :: Maybe String
+ , reqNonce :: Maybe Text
}
lookup' :: Eq a => a -> [(a, b)] -> [b]
lookup' a = map snd . filter (\x -> a == fst x)
-- | Lookup for GET parameters.
-lookupGetParams :: RequestReader m => ParamName -> m [ParamValue]
+lookupGetParams :: RequestReader m => Text -> m [Text]
lookupGetParams pn = do
rr <- getRequest
return $ lookup' pn $ reqGetParams rr
-- | Lookup for GET parameters.
-lookupGetParam :: RequestReader m => ParamName -> m (Maybe ParamValue)
+lookupGetParam :: RequestReader m => Text -> m (Maybe Text)
lookupGetParam = liftM listToMaybe . lookupGetParams
-- | Lookup for POST parameters.
lookupPostParams :: RequestReader m
- => ParamName
- -> m [ParamValue]
+ => Text
+ -> m [Text]
lookupPostParams pn = do
(pp, _) <- runRequestBody
return $ lookup' pn pp
lookupPostParam :: (MonadIO m, RequestReader m)
- => ParamName
- -> m (Maybe ParamValue)
+ => Text
+ -> m (Maybe Text)
lookupPostParam = liftM listToMaybe . lookupPostParams
-- | Lookup for POSTed files.
lookupFile :: (MonadIO m, RequestReader m)
- => ParamName
+ => Text
-> m (Maybe FileInfo)
lookupFile = liftM listToMaybe . lookupFiles
-- | Lookup for POSTed files.
lookupFiles :: RequestReader m
- => ParamName
+ => Text
-> m [FileInfo]
lookupFiles pn = do
(_, files) <- runRequestBody
return $ lookup' pn files
-- | Lookup for cookie data.
-lookupCookie :: RequestReader m => A.Ascii -> m (Maybe A.Ascii)
+lookupCookie :: RequestReader m => Text -> m (Maybe Text)
lookupCookie = liftM listToMaybe . lookupCookies
-- | Lookup for cookie data.
-lookupCookies :: RequestReader m => A.Ascii -> m [A.Ascii]
+lookupCookies :: RequestReader m => Text -> m [Text]
lookupCookies pn = do
rr <- getRequest
return $ lookup' pn $ reqCookies rr
diff --git a/Yesod/Widget.hs b/Yesod/Widget.hs
index 41cddc8e..5d863972 100644
--- a/Yesod/Widget.hs
+++ b/Yesod/Widget.hs
@@ -38,6 +38,7 @@ module Yesod.Widget
import Data.Monoid
import Control.Monad.Trans.RWS
+import Text.Blaze (preEscapedText)
import Text.Hamlet
import Text.Cassius
import Text.Julius
@@ -75,7 +76,7 @@ instance (Monad monad, a ~ ()) => HamletValue (GGWidget s m monad a) where
toHamletValue = runGWidget'
htmlToHamletMonad = GWidget' . addHtml
urlToHamletMonad url params = GWidget' $
- addHamlet $ \r -> preEscapedString (r url params)
+ addHamlet $ \r -> preEscapedText (r url params)
fromHamletValue = GWidget'
instance (Monad monad, a ~ ()) => Monad (HamletMonad (GGWidget s m monad a)) where
return = GWidget' . return
@@ -130,17 +131,17 @@ addStylesheetAttrs :: Monad m => Route master -> [(Text, Text)] -> GGWidget sub
addStylesheetAttrs x y = GWidget $ tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Local x) y) mempty mempty mempty
-- | Link to the specified remote stylesheet.
-addStylesheetRemote :: Monad m => String -> GGWidget sub master m ()
+addStylesheetRemote :: Monad m => Text -> GGWidget sub master m ()
addStylesheetRemote = flip addStylesheetRemoteAttrs []
-- | Link to the specified remote stylesheet.
-addStylesheetRemoteAttrs :: Monad m => String -> [(Text, Text)] -> GGWidget sub master m ()
+addStylesheetRemoteAttrs :: Monad m => Text -> [(Text, Text)] -> GGWidget sub master m ()
addStylesheetRemoteAttrs x y = GWidget $ tell $ GWData mempty mempty mempty (toUnique $ Stylesheet (Remote x) y) mempty mempty mempty
-addStylesheetEither :: Monad m => Either (Route master) String -> GGWidget sub master m ()
+addStylesheetEither :: Monad m => Either (Route master) Text -> GGWidget sub master m ()
addStylesheetEither = either addStylesheet addStylesheetRemote
-addScriptEither :: Monad m => Either (Route master) String -> GGWidget sub master m ()
+addScriptEither :: Monad m => Either (Route master) Text -> GGWidget sub master m ()
addScriptEither = either addScript addScriptRemote
-- | Link to the specified local script.
@@ -152,11 +153,11 @@ addScriptAttrs :: Monad m => Route master -> [(Text, Text)] -> GGWidget sub mast
addScriptAttrs x y = GWidget $ tell $ GWData mempty mempty (toUnique $ Script (Local x) y) mempty mempty mempty mempty
-- | Link to the specified remote script.
-addScriptRemote :: Monad m => String -> GGWidget sub master m ()
+addScriptRemote :: Monad m => Text -> GGWidget sub master m ()
addScriptRemote = flip addScriptRemoteAttrs []
-- | Link to the specified remote script.
-addScriptRemoteAttrs :: Monad m => String -> [(Text, Text)] -> GGWidget sub master m ()
+addScriptRemoteAttrs :: Monad m => Text -> [(Text, Text)] -> GGWidget sub master m ()
addScriptRemoteAttrs x y = GWidget $ tell $ GWData mempty mempty (toUnique $ Script (Remote x) y) mempty mempty mempty mempty
-- | Include raw Javascript in the page's script tag.
diff --git a/yesod-core.cabal b/yesod-core.cabal
index 50258068..761d95d3 100644
--- a/yesod-core.cabal
+++ b/yesod-core.cabal
@@ -8,12 +8,12 @@ synopsis: Creation of type-safe, RESTful web applications.
description:
Yesod is a framework designed to foster creation of RESTful web application that have strong compile-time guarantees of correctness. It also affords space efficient code and portability to many deployment backends, from CGI to stand-alone serving.
.
- The Yesod documentation site has much more information, tutorials and information on some of the supporting packages, like Hamlet and web-routes-quasi.
+ The Yesod documentation site has much more information, tutorials and information on some of the supporting packages, like Hamlet and web-routes-quasi.
category: Web, Yesod
stability: Stable
cabal-version: >= 1.6
build-type: Simple
-homepage: http://docs.yesodweb.com/
+homepage: http://www.yesodweb.com/
flag test
description: Build the executable to run unit tests
@@ -34,7 +34,7 @@ library
, text >= 0.5 && < 0.12
, template-haskell
, web-routes-quasi >= 0.7 && < 0.8
- , hamlet >= 0.7.3 && < 0.8
+ , hamlet >= 0.8 && < 0.9
, blaze-builder >= 0.2.1 && < 0.4
, transformers >= 0.2 && < 0.3
, clientsession >= 0.6 && < 0.7
@@ -45,7 +45,7 @@ library
, containers >= 0.2 && < 0.5
, monad-control >= 0.2 && < 0.3
, enumerator >= 0.4.7 && < 0.5
- , cookie >= 0.2 && < 0.3
+ , cookie >= 0.2.1 && < 0.3
, blaze-html >= 0.4 && < 0.5
, http-types >= 0.6 && < 0.7
, case-insensitive >= 0.2 && < 0.3