在具有非空路径的URL上创建Yesod web

时间:2012-10-02 16:13:10

标签: yesod

如果我在 settings.yml 中附加 approot 属性的基本路径,例如

为approot = “HTTP://本地主机:3000 /碱”

在浏览器中调用此URL会将“Not Found”显示为消息,而不是正确显示主页。

我找不到任何方法来解决它。

...

我知道,在将其提交到yesod任务之前,我必须重写没有基本前缀的URL,并且该批准仅用于预先添加到所有页面链接。

是否有正确的方法来处理基于URL的非空路径?

2 个答案:

答案 0 :(得分:3)

有两种相对简单的方法:

  1. 创建一个中间件,它将从pathInfo中删除前导“base”值。
  2. 覆盖cleanPath(在Yesod类型类中)以执行相同的操作。
  3. 一般情况下,如果有一些前端服务器呼叫您的Yesod应用程序(通过反向代理或FastCGI),那么带有前导路径的批准最有用。

答案 1 :(得分:2)

根据M.Snoyman的提示,这里有一个cleanPath版本,它解决了问题,只是为了由yesod init生成的ApprootMaster构造函数的批准案例,作为生成的模块基础的补充。名为.hs:

{-# LANGUAGE PackageImports #-}
import qualified Data.Text as Txt
import qualified "url" Network.URL as Url
import qualified Network.HTTP.Types as H
import qualified Data.Text.Encoding as TE
import qualified Data.List as L
import qualified "utf8-string" Data.ByteString.UTF8 as UTF8BS

-- instance Yesod App where

    -- cleanPath - A function used to clean up path segments. 
    -- It returns Right with a clean path or Left with a new set of pieces the user should be redirected to

    -- cleanPath :: Yesod a => a -> [Text] -> Either [Text] [Text]
    cleanPath master s =
        if corrected == s'
            then Right $ cutoffBasePrefix s'
            else Left $ cutoffBasePrefix corrected   -- to be redirected
      where
        -- avoid redirection on slash ended urls by junking the last piece if it's null

        s' = if not (L.null s) && Txt.null (last s) then init s else s

        corrected = filter (not . Txt.null) s'

        -- strToUtf8BS = TE.encodeUtf8 . Txt.pack  -- packs to UTF16 then encodes to UTF8
        strToUtf8BS = UTF8BS.fromString

        -- cut off "base prefix" or leave as it is

        cutoffBasePrefix segmts =
                case approot of
                     ApprootMaster f ->
                         case Url.importURL $ Txt.unpack $ f master of
                              Nothing -> segmts   -- not expected, incorrect url in settings.yml approot
                              Just url -> let basePrefixSegmts = H.decodePathSegments $ strToUtf8BS $ Url.url_path url in
                                          case basePrefixSegmts of
                                               [] -> segmts
                                               _ -> if basePrefixSegmts `L.isPrefixOf` segmts
                                                       then drop (length basePrefixSegmts) segmts
                                                       else segmts


                     _ -> segmts

使用theese其他包依赖项:

, url                           >= 2.1.2
, network
, http-types
, utf8-string