8

我正在尝试将一些转发ByteString回客户端(浏览器)。客户端将不知道所请求文档的内容类型,因此我试图将适当的内容类型响应发送回客户端。该文档可以是图像或pdf或word文档等。

例如,客户端将请求/document?id=55,服务器将使用适当的内容类型和关联的ByteString.

我按照这里的例子:我为图像创建了一些东西。

 data IMAGE

 instance Accept IMAGE where
     contentType _ = "image" M.// "jpeg"

 instance MimeRender IMAGE LBS.ByteString where
     mimeRender _ = id

挑战是客户端不会发送带有某些特定标头的请求,因此我无法像在此处Accept:完成的那样对适当的 Mime 类型做出反应。另外,上述内容仅适用于图像(假设浏览器会推断出我发回的内容),但不适用于,等。pngjpegpdfdocx

我考虑了一个参数化类型,例如MyDynamicContent String,我将在运行时传入内容类型,但我不确定如何声明我的 API,即我将使用什么来代替'[JSON]. 甚至不确定这样的事情是否可能,因为这些示例只是一个简单的数据类型。

所以我的问题是,如果我想发送一些ByteString作为响应并Content-Type动态设置标题,那么使用它的最佳方法是什么servant

更新:我打开了一个问题

4

1 回答 1

4

这是可能的,但有点hack:

{-# 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-clientservant-docs鉴于此,您可能希望在 repo 中打开一个关于此的问题以获得更完整的支持。

于 2016-02-26T17:59:17.080 回答