2016-04-02 62 views
3

我有一个简单的hello world Servant应用程序。我需要添加一些静态或动态的HTML页面。我怎样才能做到这一点?在文档中没有提到。注意我不想在Haskell代码中创建html布局,我希望Haskell显示已经创建的html页面。仆人中的HTML页面 - 如何结合REST API和静态html页面?

UPDATE:

我如何结合这一点:

type MyApi = "/" :> Raw 

server :: Server MyApi 
server = serveDirectory "static/" -- index.html, about.html 

与我已经:

​​

UPDATE2:

工作:

type API = 
    "api" :> "items" :> Get '[JSON] [MyData] :<|> 
    "api" :> "items" :> Capture "id" Int :> Get '[JSON] MyData :<|> 
    Raw 

没有工作,没有任何反应都:

type API = 
    "api" :> "items" :> Get '[JSON] [MyData] :<|> 
    "api" :> "items" :> Capture "id" Int :> Get '[JSON] MyData :<|> 
    "/" :> Raw 

-- or 

type API = 
    "api" :> "items" :> Get '[JSON] [MyData] :<|> 
    "api" :> "items" :> Capture "id" Int :> Get '[JSON] MyData :<|> 
    "" :> Raw 

我不知道为什么?

+0

你可以做'serveDirectory'如果你的静态页面已经在正确的结构。 – zakyggaps

+0

@zakyggaps,已更新。 –

+0

仆人API将按照从上到下的顺序进行匹配。你可以把它放在最后一行。 – zakyggaps

回答

5

如何结合REST API和静态html页面?

您可以通过serveDirectory在根路径上提供包含静态网站的目录。它必须是您的仆人API中的最后一个案例,否则将永远不会匹配其他案例。

type API = 
    "api" :> "items" :> Get '[JSON] [MyData] :<|> 
    "api" :> "items" :> Capture "id" Int :> Get '[JSON] MyData :<|> 
    Raw 

api :: Proxy API 
api = Proxy 

server :: Server API 
server = getItems 
    :<|> getItem 
    :<|> serveDirectory "static/" 

此外,如果任何静态页面名称与您的API崩溃,它将被遮蔽。


为什么不是"/" :> Raw

看起来像我的浏览器缓存了一些静态页面。清理缓存后,"/" :> Raw/index.html下没有回应。

api中的字符串文字将首先编码为合法的uri部分,因此"/"将为"%2F",并且您的文件被映射到/%2F/index.html等等。


你知道我怎么能处理的根源呢?

要服务于根路径的响应,你可以定义一个Get端点没有前缀:

type API = Get '[HTML] RawHtml 

它可以是除最后一行的API中的任何位置。

服务于一个本地文件为HTML响应,你必须区别于其他字节串的文件,也许在NEWTYPE包装它:

newtype RawHtml = RawHtml { unRaw :: BS.ByteString } 

-- tell Servant how to render the newtype to html page, in this case simply unwrap it 
instance MimeRender HTML RawHtml where 
    mimeRender _ = unRaw 

,并在你的控制器:

-- ... 
:<|> fmap RawHtml (liftIO $ BS.readFile "your/file/path.html") 

或者,如果该页面已有另一个地址,您可以将用户重定向到那里:

-- ... 
:<|> throwError err301 { errHeaders = [("Location", "index.html")] } 

它已经返回index.html。嗯,为什么究竟index.html?

serveDirectory调用wai应用程序staticApp设置defaultFileServerSettings。在该环境中的用户将被重定向到index.htmindex.html如果出事了:

defaultFileServerSettings root = StaticSettings 
    { ssLookupFile = fileSystemLookup (fmap Just . hashFile) root 
    , ssMkRedirect = defaultMkRedirect 
    , ssGetMimeType = return . defaultMimeLookup . fromPiece . fileName 
    , ssMaxAge = NoMaxAge 
    , ssListing = Just defaultListing 
    , ssIndices = map unsafeToPiece ["index.html", "index.htm"] 
    , ssRedirectToIndex = False 
    , ssUseHash = False 
    , ssAddTrailingSlash = False 
    , ss404Handler = Nothing 
    } 
+0

为什么不是':<|>“”:> Raw'或':<|>“/”:> Raw'?为什么只是':<|> Raw'? –

+0

'Raw'和'“/”:> Raw'都将指向根路径。我选择了较短的。 – zakyggaps

+0

其实':<|>“”:> Raw'和':<|>“/”:> Raw'没有工作。服务器不会返回任何内容,例如找不到。我想知道为什么? –