1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE PolyKinds #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE TypeOperators #-}
11{-# LANGUAGE UndecidableInstances #-}
12module Servant.API.ContentTypes where
16import Control.Monad (join)
17import qualified Data.ByteString as BS
18import Data.ByteString.Lazy (ByteString)
19import Data.String.Conversions (cs)
20import GHC.Exts (Constraint)
21import qualified Network.HTTP.Media as M
23-- * Provided content types
24data XML deriving Typeable
25data HTML deriving Typeable
26data JSON deriving Typeable
27data JavaScript deriving Typeable
28data CSS deriving Typeable
29data PlainText deriving Typeable
30data OctetStream deriving Typeable
34-- | Instances of 'Accept' represent mimetypes. They are used for matching
35-- against the @Accept@ HTTP header of the request, and for setting the
36-- @Content-Type@ header of the response
40-- > instance Accept HTML where
41-- > contentType _ = "text" // "html"
43class Accept ctype where
44 contentType :: Proxy ctype -> M.MediaType
46-- | @text/html;charset=utf-8@
47instance Accept HTML where
48 contentType _ = "text" M.// "html" M./: ("charset", "utf-8")
50-- | @application/json;charset=utf-8@
51instance Accept JSON where
52 contentType _ = "application" M.// "json" M./: ("charset", "utf-8")
54-- | @application/xml;charset=utf-8@
55instance Accept XML where
56 contentType _ = "application" M.// "xml" M./: ("charset", "utf-8")
58-- | @application/javascript;charset=utf-8@
59instance Accept JavaScript where
60 contentType _ = "application" M.// "javascript" M./: ("charset", "utf-8")
62-- | @text/css;charset=utf-8@
63instance Accept CSS where
64 contentType _ = "text" M.// "css" M./: ("charset", "utf-8")
66-- | @text/plain;charset=utf-8@
67instance Accept PlainText where
68 contentType _ = "text" M.// "plain" M./: ("charset", "utf-8")
70-- | @application/octet-stream@
71instance Accept OctetStream where
72 contentType _ = "application" M.// "octet-stream"
74newtype AcceptHeader = AcceptHeader BS.ByteString
77-- * Render (serializing)
79-- | Instantiate this class to register a way of serializing a type based
80-- on the @Accept@ header.
84-- > data MyContentType
86-- > instance Accept MyContentType where
87-- > contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
89-- > instance Show a => MimeRender MyContentType where
90-- > toByteString _ val = pack ("This is MINE! " ++ show val)
92-- > type MyAPI = "path" :> Get '[MyContentType] Int
93class Accept ctype => MimeRender ctype a where
94 toByteString :: Proxy ctype -> a -> ByteString
96class AllCTRender list a where
97 -- If the Accept header can be matched, returns (Just) a tuple of the
98 -- Content-Type and response (serialization of @a@ into the appropriate
100 handleAcceptH :: Proxy list -> AcceptHeader -> a -> Maybe (ByteString, ByteString)
102instance ( AllMimeRender ctyps a, IsNonEmpty ctyps
103 ) => AllCTRender ctyps a where
104 handleAcceptH _ (AcceptHeader accept) val = M.mapAcceptMedia lkup accept
105 where pctyps = Proxy :: Proxy ctyps
106 amrs = amr pctyps val
107 lkup = zip (map fst amrs) $ map (\(a,b) -> (cs $ show a, b)) amrs
112--------------------------------------------------------------------------
114class Accept ctype => MimeUnrender ctype a where
115 fromByteString :: Proxy ctype -> ByteString -> Maybe a
117class AllCTUnrender list a where
118 handleCTypeH :: Proxy list
119 -> ByteString -- Content-Type header
120 -> ByteString -- Request body
123instance ( AllMimeUnrender ctyps a, IsNonEmpty ctyps
124 ) => AllCTUnrender ctyps a where
125 handleCTypeH _ ctypeH body = join $ M.mapContentMedia lkup (cs ctypeH)
126 where lkup = amu (Proxy :: Proxy ctyps) body
128--------------------------------------------------------------------------
132--------------------------------------------------------------------------
133-- Check that all elements of list are instances of MimeRender
134--------------------------------------------------------------------------
135class AllMimeRender ls a where
137 -> a -- value to serialize
138 -> [(M.MediaType, ByteString)] -- content-types/response pairs
140instance ( MimeRender ctyp a ) => AllMimeRender '[ctyp] a where
141 amr _ a = [(contentType pctyp, toByteString pctyp a)]
142 where pctyp = Proxy :: Proxy ctyp
144instance ( MimeRender ctyp a
145 , MimeRender ctyp' a -- at least two elems to avoid overlap
146 , AllMimeRender ctyps a
147 ) => AllMimeRender (ctyp ': ctyp' ': ctyps) a where
148 amr _ a = (contentType pctyp, toByteString pctyp a)
149 :(contentType pctyp', toByteString pctyp' a)
151 where pctyp = Proxy :: Proxy ctyp
152 pctyps = Proxy :: Proxy ctyps
153 pctyp' = Proxy :: Proxy ctyp'
156instance AllMimeRender '[] a where
159--------------------------------------------------------------------------
160-- Check that all elements of list are instances of MimeUnrender
161--------------------------------------------------------------------------
162class AllMimeUnrender ls a where
163 amu :: Proxy ls -> ByteString -> [(M.MediaType, Maybe a)]
165instance ( MimeUnrender ctyp a ) => AllMimeUnrender '[ctyp] a where
166 amu _ val = [(contentType pctyp, fromByteString pctyp val)]
167 where pctyp = Proxy :: Proxy ctyp
169instance ( MimeUnrender ctyp a
170 , MimeUnrender ctyp' a
171 , AllMimeUnrender ctyps a
172 ) => AllMimeUnrender (ctyp ': ctyp' ': ctyps) a where
173 amu _ val = (contentType pctyp, fromByteString pctyp val)
174 :(contentType pctyp', fromByteString pctyp' val)
176 where pctyp = Proxy :: Proxy ctyp
177 pctyps = Proxy :: Proxy ctyps
178 pctyp' = Proxy :: Proxy ctyp'
180type family IsNonEmpty (ls::[*]) :: Constraint where
181 IsNonEmpty '[] = 'False ~ 'True
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list