![](/img/trans.png)
[英]Why is the default catch-all not mandatory in a Haskell case statement?
[英]Catch-all or default routing
如今,如果請求的路由與現有的API端點或其他靜態資產不匹配,則需要從后端返回文件(例如index.html
)已經很常見了。 這在使用react-router
和browserHistory
時特別方便。
我對如何使用Servant感到困惑。 我確實想知道是否可以通過攔截404來解決問題,但是當然,有時API會需要合法地發出404。這是我一直在嘗試的事情:
data Wombat = Wombat
{ id :: Int
, name :: String
} deriving (Eq, Show, Generic)
instance ToJSON Wombat
wombatStore :: [Wombat]
wombatStore =
[ Wombat 0 "Gertrude"
, Wombat 1 "Horace"
, Wombat 2 "Maisie"
, Wombat 3 "Julius"
]
wombats :: Handler [Wombat]
wombats = return wombatStore
wombat :: Int -> Handler Wombat
wombat wid = do
case find (\w -> Main.id w == wid) wombatStore of
Just x -> return x
Nothing -> throwE err404
type API =
"api" :> "wombats" :> Get '[JSON] [Wombat] :<|>
"api" :> "wombats" :> Capture "id" Int :> Get '[JSON] Wombat :<|>
Raw
api :: Proxy API
api = Proxy
server :: Server API
server = wombats
:<|> wombat
:<|> serveDirectory "static"
app :: Application
app = serve api server
main :: IO ()
main = run 3000 app
我很樂意看到一個示例,說明如何添加一個“默認路由”,如果請求與API端點或靜態目錄中的任何內容都不匹配,該默認路由將發送HTML響應。 玩具回購在這里 。
基本上,您明白了。 serveDirectory "static"
可以用任何wai Application
代替,例如,我們可以這樣:
...
{-# LANGUAGE OverloadedStrings #-}
...
import Network.Wai (responseLBS)
import Network.HTTP.Types (status200)
...
server :: Server API
server = wombats
:<|> wombat
:<|> hello
hello :: Application
hello req respond = respond $
responseLBS
status200 --
[("Content-Type", "text/plain")] -- headers
"Hello, World!" -- content
...
大致來說,wai應用程序只是Request -> Response
,但是文檔講述了一個完整的故事:
Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
因此,由於您可以訪問IO,因此可以檢查文件是否存在以及是否可以提供文件,否則可以執行任何操作。 實際上,wai定義了type Middleware = Application -> Application
,因此您可能會想到一個方便的中間件,該中間件在文件存在檢查器和服務器中打包了hello
(或任何其他Application!)。
這是另一條路線:
serveDirectory
定義為
serveDirectory = staticApp . defaultFileServerSettings . addTrailingPathSeparator
defaultFileServerSettings
包含一個字段ssLookupFile
,如果找不到該文件,則可以更改該字段以提供所需的內容。 也許:
import WaiAppStatic.Types
import WaiAppStatic.Storage.Filesystem
import Network.Wai.Application.Static
import System.FilePath
fileOrIndex root pieces = do
res <- ssLookupFile (defaultFileServerSettings root) pieces
case res of
LRNotFound -> undefined -- index.html here
_ -> return res
serveStatic root =
let root' = addTrailingPathSeparator root in
staticApp $ (defaultFileServerSettings root') {ssLookupFile = fileOrIndex root'}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.