@@ -24,10 +24,14 @@ import qualified Data.Text as T
2424import Data.Typeable
2525import GHC.TypeLits (KnownSymbol, symbolVal)
2626import Network.HTTP.Types hiding (Header)
27−import Network.Wai (Response, Request, ResponseReceived, Application, pathInfo, requestBody,
28− strictRequestBody, lazyRequestBody, requestHeaders, requestMethod,
27+import Network.Wai ( Response, Request, ResponseReceived, Application
28+ , pathInfo, requestBody, strictRequestBody
29+ , lazyRequestBody, requestHeaders, requestMethod,
2930 rawQueryString, responseLBS)
30−import Servant.API (QueryParams, QueryParam, QueryFlag, MatrixParams, MatrixParam, MatrixFlag, ReqBody, Header, Capture, Get, Delete, Put, Post, Patch, Raw, (:>), (:<|>)(..))
31+import Servant.API ( QueryParams, QueryParam, QueryFlag, ReqBody, Header
32+ , MatrixParams, MatrixParam, MatrixFlag,
33+ , Capture, Get, Delete, Put, Post, Patch, Raw, (:>), (:<|>)(..))
34+import Servant.Server.ContentTypes (AllCTRender(..), AcceptHeader(..))
3135import Servant.Common.Text (FromText, fromText)
3236
3337data ReqBodyState = Uncalled
@@ -225,7 +229,7 @@ instance (KnownSymbol capture, FromText a, HasServer sublayout)
225229 _ -> respond $ failWith NotFound
226230
227231 where captureProxy = Proxy :: Proxy (Capture capture a)
228−
232+
229233
230234-- | If you have a 'Delete' endpoint in your API,
231235-- the handler for this endpoint is meant to delete
@@ -264,14 +268,19 @@ instance HasServer Delete where
264268-- If successfully returning a value, we just require that its type has
265269-- a 'ToJSON' instance and servant takes care of encoding it for you,
266270-- yielding status code 200 along the way.
267−instance ToJSON result => HasServer (Get result) where
268− type Server (Get result) = EitherT (Int, String) IO result
271+instance ( AllCTRender ctypes a, ToJSON a
272+ ) => HasServer (Get ctypes a) where
273+ type Server (Get ctypes a) = EitherT (Int, String) IO a
269274 route Proxy action request respond
270275 | pathIsEmpty request && requestMethod request == methodGet = do
271276 e <- runEitherT action
272277 respond . succeedWith $ case e of
273− Right output ->
274− responseLBS ok200 [("Content-Type", "application/json")] (encode output)
278+ Right output -> do
279+ let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
280+ case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
281+ Nothing -> responseLBS (mkStatus 406 "") [] ""
282+ Just (contentT, body) -> responseLBS ok200 [ ("Content-Type"
283+ , cs contentT)] body
275284 Left (status, message) ->
276285 responseLBS (mkStatus status (cs message)) [] (cs message)
277286 | pathIsEmpty request && requestMethod request /= methodGet =
@@ -321,15 +330,20 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
321330-- If successfully returning a value, we just require that its type has
322331-- a 'ToJSON' instance and servant takes care of encoding it for you,
323332-- yielding status code 201 along the way.
324−instance ToJSON a => HasServer (Post a) where
325− type Server (Post a) = EitherT (Int, String) IO a
333+instance ( AllCTRender ctypes a, ToJSON a
334+ )=> HasServer (Post ctypes a) where
335+ type Server (Post ctypes a) = EitherT (Int, String) IO a
326336
327337 route Proxy action request respond
328338 | pathIsEmpty request && requestMethod request == methodPost = do
329339 e <- runEitherT action
330340 respond . succeedWith $ case e of
331− Right out ->
332− responseLBS status201 [("Content-Type", "application/json")] (encode out)
341+ Right output -> do
342+ let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
343+ case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
344+ Nothing -> responseLBS (mkStatus 406 "") [] ""
345+ Just (contentT, body) -> responseLBS status201 [ ("Content-Type"
346+ , cs contentT)] body
333347 Left (status, message) ->
334348 responseLBS (mkStatus status (cs message)) [] (cs message)
335349 | pathIsEmpty request && requestMethod request /= methodPost =
@@ -347,15 +361,20 @@ instance ToJSON a => HasServer (Post a) where
347361-- If successfully returning a value, we just require that its type has
348362-- a 'ToJSON' instance and servant takes care of encoding it for you,
349363-- yielding status code 200 along the way.
350−instance ToJSON a => HasServer (Put a) where
351− type Server (Put a) = EitherT (Int, String) IO a
364+instance ( AllCTRender ctypes a, ToJSON a
365+ ) => HasServer (Put ctypes a) where
366+ type Server (Put ctypes a) = EitherT (Int, String) IO a
352367
353368 route Proxy action request respond
354369 | pathIsEmpty request && requestMethod request == methodPut = do
355370 e <- runEitherT action
356371 respond . succeedWith $ case e of
357− Right out ->
358− responseLBS ok200 [("Content-Type", "application/json")] (encode out)
372+ Right output -> do
373+ let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
374+ case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
375+ Nothing -> responseLBS (mkStatus 406 "") [] ""
376+ Just (contentT, body) -> responseLBS status200 [ ("Content-Type"
377+ , cs contentT)] body
359378 Left (status, message) ->
360379 responseLBS (mkStatus status (cs message)) [] (cs message)
361380 | pathIsEmpty request && requestMethod request /= methodPut =
@@ -382,7 +401,7 @@ instance (Typeable a, ToJSON a) => HasServer (Patch a) where
382401 e <- runEitherT action
383402 respond . succeedWith $ case e of
384403 Right out -> case cast out of
385− Nothing -> responseLBS status200 [("Content-Type", "application/json")] (encode out)
404+ Nothing -> responseLBS status200 [("Content-Type", "application/json")] (encode out)
386405 Just () -> responseLBS status204 [] ""
387406 Left (status, message) ->
388407 responseLBS (mkStatus status (cs message)) [] (cs message)