2016-02-25 18 views
6

Tôi đang cố gắng chuyển tiếp một số ByteString quay lại máy khách (trình duyệt). Khách hàng sẽ không biết loại nội dung của tài liệu đang được yêu cầu vì vậy tôi đang cố gửi phản hồi kiểu nội dung thích hợp cho khách hàng. Tài liệu có thể là hình ảnh hoặc pdf hoặc tài liệu từ, v.v.Gửi loại nội dung chung trong Servant

Ví dụ: khách hàng sẽ yêu cầu /document?id=55 và máy chủ sẽ phản hồi với loại nội dung thích hợp và liên kết ByteString.

Tôi đã làm theo ví dụ here: và tôi đã tạo thứ gì đó cho hình ảnh.

data IMAGE 

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

instance MimeRender IMAGE LBS.ByteString where 
    mimeRender _ = id 

Thách thức là khách hàng sẽ không được gửi yêu cầu với một số Accept: tiêu đề cụ thể như vậy không có cách nào cho tôi phản ứng với một Mime Type thích hợp như nó được thực hiện here. Plus ở trên sẽ chỉ làm việc cho hình ảnh (giả sử trình duyệt sẽ suy ra một png thậm chí tôi gửi lại jpeg) nhưng không cho pdf, docx, v.v.

Tôi đã nghĩ về loại tham số như MyDynamicContent String và tôi sẽ chuyển loại nội dung vào thời gian chạy nhưng tôi không chắc chắn cách khai báo API của mình, tôi sẽ sử dụng cái gì thay vì '[JSON]. Bạn không chắc chắn điều đó thậm chí có thể là các ví dụ chỉ là một kiểu dữ liệu đơn giản.

Vì vậy, câu hỏi của tôi là, nếu tôi muốn gửi một số ByteString như một phản ứng và thiết lập Content-Type tiêu đề tự động, điều gì sẽ là cách tốt nhất để làm điều đó bằng servant

Cập nhật: Tôi đã mở một issue

+0

Máy chủ quyết định loại nội dung nào sẽ phản hồi? (Cụ thể, chỉ để chắc chắn, điều này không thể được xác định tĩnh?) – user2141650

+0

@ user2141650: Máy chủ 'nhận thông tin này từ kho dữ liệu (dịch vụ lưu trữ tài liệu). Nó thực hiện cuộc gọi đến dịch vụ và dịch vụ đáp ứng với kiểu nội dung và cũng là chuỗi byte. Tôi biết tôi có thể tạo điểm kết thúc cho từng loại nội dung (hoặc ít nhất là sử dụng) và gửi kiểu nội dung trước rồi yêu cầu khách hàng sử dụng điểm cuối tương ứng với loại nội dung. Đây là một hack xấu, di chuyển rất nhiều logic này cho khách hàng, tôi cảm thấy nó sẽ được xử lý tốt hơn bởi máy chủ. – Ecognium

Trả lời

3

có thể, nhưng một chút của một 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 

kiểm tra nó:

% curl localhost:8000 -v 
... 
< HTTP/1.1 200 OK 
... 
< Content-Type: example 
< 
... 
somecontent% 

Ý tưởng chỉ là ghi đè hành vi bình thường bằng cách tuyên bố một phiên bản chồng chéo cho AllCTRender. Lưu ý rằng có thể bạn cũng sẽ phải thực hiện thêm một số công việc chân cho servant-client, servant-docs v.v. nếu bạn cũng đang sử dụng chúng. Cho rằng, bạn có thể muốn mở một vấn đề trong repo về việc này để được hỗ trợ đầy đủ hơn.

+0

Cảm ơn bạn rất nhiều. Điều này thực sự hoạt động. Tôi đang sử dụng 'servant-docs' và tôi đang gặp lỗi kiểu. Bạn đã biết điều này sẽ là một vấn đề. Không chắc chắn những gì tôi cần phải cung cấp để đáp ứng các tài liệu để sử dụng ''[]'. Lỗi tôi nhận được là 'Không thể suy ra (Servant.API.ContentTypes.IsNonEmpty' []) phát sinh từ việc sử dụng ‘Doc.docs''. Tôi sẽ mở một vấn đề và xem liệu có một cách sạch sẽ để giải quyết vấn đề tài liệu hay không. – Ecognium

+0

Tôi đã làm cho nó hoạt động với các tài liệu. Thay vì sử dụng ''[]' Tôi chỉ sử dụng một loại mime tùy chỉnh chung chung. Kiểu nội dung của cá thể Accept chấp nhận được 'AllCTRender' được overriden để hoạt động tốt.Bằng cách này tôi có thể sử dụng các tài liệu và trả về một loại mime tùy chỉnh. – Ecognium

Các vấn đề liên quan