簡體   English   中英

全部或默認路由

[英]Catch-all or default routing

如今,如果請求的路由與現有的API端點或其他靜態資產不匹配,則需要從后端返回文件(例如index.html )已經很常見了。 這在使用react-routerbrowserHistory時特別方便。

我對如何使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM