我正在尝试将一些ByteString
转发回客户端(浏览器)。客户端将不知道所请求文档的内容类型,因此我尝试将适当的内容类型响应发送回客户端。该文件可以是图像或pdf或word文档等。
例如,客户端将请求/document?id=55
,服务器将使用相应的内容类型和关联的ByteString
进行响应。
我按照示例here:我为图像创建了一些东西。
data IMAGE
instance Accept IMAGE where
contentType _ = "image" M.// "jpeg"
instance MimeRender IMAGE LBS.ByteString where
mimeRender _ = id
挑战是客户端不会使用某个特定的Accept:
标头发送请求,因此我无法像使用here那样对适当的Mime类型做出反应。此外,上述内容仅适用于图片(假设浏览器会推断png
,即使我发回jpeg
),也不会推送pdf
,docx
等。
我考虑过像MyDynamicContent String
这样的参数化类型,我会在运行时传递内容类型,但我不确定如何声明我的API,即我将使用什么代替{{1} }。不确定这样的事情是否可能,因为示例只是一个简单的数据类型。
所以我的问题是,如果我想发送一些'[JSON]
作为回复并动态设置ByteString
标头,那么使用Content-Type
}的最佳方法是什么
更新:我打开了issue
答案 0 :(得分:3)
这是可能的,但有点黑客:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverlappingInstances #-}
module DynCT where
import Control.Monad.Trans.Either
import Data.ByteString.Lazy (ByteString)
import Servant
import Servant.API.ContentTypes
import Network.Wai.Handler.Warp
data WithCT = WithCT { header :: ByteString, content :: ByteString }
instance AllCTRender xs WithCT where
handleAcceptH _ _ (WithCT h c) = Just (h, c)
type API = Get '[] WithCT
api :: Proxy API
api = Proxy
server :: Server API
server = return $ WithCT { header = "example", content = "somecontent" }
main :: IO ()
main = run 8000 $ serve api server
测试它:
% curl localhost:8000 -v
...
< HTTP/1.1 200 OK
...
< Content-Type: example
<
...
somecontent%
这个想法只是通过声明AllCTRender
的重叠实例来覆盖正常行为。请注意,如果您还使用这些内容,您可能还需要为servant-client
,servant-docs
等进行一些额外的工作。鉴于此,您可能希望在回购中打开一个有关此问题的问题,以获得更完整的支持。