packages feed

serv 0.1.0.0 → 0.2.0.0

raw patch · 33 files changed

+350/−2844 lines, 33 filesdep +http-kinderdep +singletonsdep −HUnitdep −QuickCheckdep −aesondep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: http-kinder, singletons

Dependencies removed: HUnit, QuickCheck, aeson, bytestring, case-insensitive, http-media, http-types, mtl, serv, tagged, tasty, tasty-ant-xml, tasty-hunit, tasty-quickcheck, time, transformers, wai, wai-extra, warp

Dependency ranges changed: base

API changes (from Hackage documentation)

- Serv.Api: (:::) :: a -> b -> Pair a b
- Serv.Api: DELETE :: Verb
- Serv.Api: GET :: Verb
- Serv.Api: HEAD :: Verb
- Serv.Api: OPTIONS :: Verb
- Serv.Api: PATCH :: Verb
- Serv.Api: POST :: Verb
- Serv.Api: PUT :: Verb
- Serv.Api: [:>] :: Path star -> Api star -> Api star
- Serv.Api: [Body] :: [star] -> star -> Body star
- Serv.Api: [CaptureBody] :: [star] -> star -> Method star -> Method star
- Serv.Api: [CaptureHeaders] :: [Pair HeaderName star] -> Method star -> Method star
- Serv.Api: [CaptureQuery] :: [Pair Symbol star] -> Method star -> Method star
- Serv.Api: [Const] :: Symbol -> Path star
- Serv.Api: [Cors] :: star -> Path star
- Serv.Api: [Empty] :: Body star
- Serv.Api: [Endpoint] :: [Method star] -> Api star
- Serv.Api: [Flag] :: Symbol -> Path star
- Serv.Api: [HeaderAs] :: HeaderName -> Symbol -> Path star
- Serv.Api: [Header] :: HeaderName -> star -> Path star
- Serv.Api: [Method] :: Verb -> [Pair HeaderName star] -> Body star -> Method star
- Serv.Api: [OneOf] :: [Api star] -> Api star
- Serv.Api: [QueryParam] :: Symbol -> star -> Path star
- Serv.Api: [Raw] :: Api star
- Serv.Api: [Seg] :: Symbol -> star -> Path star
- Serv.Api: [Wildcard] :: Path star
- Serv.Api: data Method star
- Serv.Api: data Pair a b
- Serv.Api: data Verb
- Serv.Common: RawText :: Text -> RawText
- Serv.Common: [getRawText] :: RawText -> Text
- Serv.Common: newtype RawText
- Serv.ContentType: (//) :: ByteString -> ByteString -> MediaType
- Serv.ContentType: (/:) :: MediaType -> (ByteString, ByteString) -> MediaType
- Serv.ContentType: class HasMediaType ty
- Serv.ContentType: class HasMediaType ty => MimeDecode ty val
- Serv.ContentType: class HasMediaType ty => MimeEncode ty val
- Serv.ContentType: data JSON
- Serv.ContentType: data TextPlain
- Serv.ContentType: instance Data.Aeson.Types.FromJSON.FromJSON a => Serv.Internal.MediaType.MimeDecode Serv.ContentType.JSON a
- Serv.ContentType: instance Data.Aeson.Types.ToJSON.ToJSON a => Serv.Internal.MediaType.MimeEncode Serv.ContentType.JSON a
- Serv.ContentType: instance Serv.Internal.MediaType.HasMediaType Serv.ContentType.JSON
- Serv.ContentType: instance Serv.Internal.MediaType.HasMediaType Serv.ContentType.TextPlain
- Serv.ContentType: instance Serv.Internal.MediaType.MimeEncode Serv.ContentType.TextPlain Data.Text.Internal.Text
- Serv.ContentType: mediaType :: HasMediaType ty => Proxy ty -> MediaType
- Serv.ContentType: mimeDecode :: MimeDecode ty val => Proxy ty -> ByteString -> Either String val
- Serv.ContentType: mimeEncode :: MimeEncode ty val => Proxy ty -> val -> ByteString
- Serv.Cors: AccessSet :: Bool -> Set HeaderName -> Bool -> Set Verb -> Set HeaderName -> Maybe NominalDiffTime -> AccessSet
- Serv.Cors: Context :: Text -> Set HeaderName -> Set HeaderName -> Set Verb -> Context
- Serv.Cors: [credentialsAllowed] :: AccessSet -> Bool
- Serv.Cors: [headersAllowed] :: AccessSet -> Set HeaderName
- Serv.Cors: [headersExpected] :: Context -> Set HeaderName
- Serv.Cors: [headersExposed] :: AccessSet -> Set HeaderName
- Serv.Cors: [headersReturned] :: Context -> Set HeaderName
- Serv.Cors: [maxAge] :: AccessSet -> Maybe NominalDiffTime
- Serv.Cors: [methodsAllowed] :: AccessSet -> Set Verb
- Serv.Cors: [methodsAvailable] :: Context -> Set Verb
- Serv.Cors: [originAllowed] :: AccessSet -> Bool
- Serv.Cors: [origin] :: Context -> Text
- Serv.Cors: class CorsPolicy m
- Serv.Cors: corsPolicy :: CorsPolicy m => Proxy m -> Policy
- Serv.Cors: data AccessSet
- Serv.Cors: data Context
- Serv.Cors: data PermitAll
- Serv.Cors: permitAll :: Policy
- Serv.Cors: predicateWhitelist :: (Text -> Bool) -> Policy
- Serv.Cors: type Policy = Config -> Context -> AccessSet
- Serv.Cors: wildcard :: Policy
- Serv.Header: Accept :: HeaderName
- Serv.Header: AcceptCharset :: HeaderName
- Serv.Header: AcceptEncoding :: HeaderName
- Serv.Header: AcceptLanguage :: HeaderName
- Serv.Header: AcceptPatch :: HeaderName
- Serv.Header: AcceptRanges :: HeaderName
- Serv.Header: AccessControlAllowCredentials :: HeaderName
- Serv.Header: AccessControlAllowHeaders :: HeaderName
- Serv.Header: AccessControlAllowMethods :: HeaderName
- Serv.Header: AccessControlAllowOrigin :: HeaderName
- Serv.Header: AccessControlExposeHeaders :: HeaderName
- Serv.Header: AccessControlMaxAge :: HeaderName
- Serv.Header: AccessControlRequestHeaders :: HeaderName
- Serv.Header: AccessControlRequestMethod :: HeaderName
- Serv.Header: Age :: HeaderName
- Serv.Header: Allow :: HeaderName
- Serv.Header: Authorization :: HeaderName
- Serv.Header: CacheControl :: HeaderName
- Serv.Header: Connection :: HeaderName
- Serv.Header: ContentDisposition :: HeaderName
- Serv.Header: ContentEncoding :: HeaderName
- Serv.Header: ContentLanguage :: HeaderName
- Serv.Header: ContentLength :: HeaderName
- Serv.Header: ContentLocation :: HeaderName
- Serv.Header: ContentRange :: HeaderName
- Serv.Header: ContentSecurityPolicy :: HeaderName
- Serv.Header: ContentType :: HeaderName
- Serv.Header: Cookie :: HeaderName
- Serv.Header: Date :: HeaderName
- Serv.Header: ETag :: HeaderName
- Serv.Header: Expect :: HeaderName
- Serv.Header: Expires :: HeaderName
- Serv.Header: From :: HeaderName
- Serv.Header: HeaderName :: Symbol -> HeaderName
- Serv.Header: Host :: HeaderName
- Serv.Header: IfMatch :: HeaderName
- Serv.Header: IfModifiedSince :: HeaderName
- Serv.Header: IfNoneMatch :: HeaderName
- Serv.Header: IfRange :: HeaderName
- Serv.Header: IfUnmodifiedSince :: HeaderName
- Serv.Header: LastModified :: HeaderName
- Serv.Header: Link :: HeaderName
- Serv.Header: Location :: HeaderName
- Serv.Header: MaxForwards :: HeaderName
- Serv.Header: Origin :: HeaderName
- Serv.Header: Pragma :: HeaderName
- Serv.Header: ProxyAuthenticate :: HeaderName
- Serv.Header: ProxyAuthorization :: HeaderName
- Serv.Header: PublicKeyPins :: HeaderName
- Serv.Header: Range :: HeaderName
- Serv.Header: Referer :: HeaderName
- Serv.Header: RetryAfter :: HeaderName
- Serv.Header: SetCookie :: HeaderName
- Serv.Header: StrictTransportSecurity :: HeaderName
- Serv.Header: TE :: HeaderName
- Serv.Header: Trailer :: HeaderName
- Serv.Header: TransferEncoding :: HeaderName
- Serv.Header: Upgrade :: HeaderName
- Serv.Header: UserAgent :: HeaderName
- Serv.Header: Vary :: HeaderName
- Serv.Header: Via :: HeaderName
- Serv.Header: WWWAuthenticate :: HeaderName
- Serv.Header: Warning :: HeaderName
- Serv.Header: XCsrfToken :: HeaderName
- Serv.Header: XForwardedFor :: HeaderName
- Serv.Header: XForwardedHost :: HeaderName
- Serv.Header: XForwardedProto :: HeaderName
- Serv.Header: class ReflectName n => HeaderDecode (n :: HeaderName) a
- Serv.Header: class ReflectName n => HeaderEncode (n :: HeaderName) a
- Serv.Header: class ReflectName (n :: HeaderName)
- Serv.Header: data HeaderName
- Serv.Header: headerDecode :: HeaderDecode n a => Proxy n -> Maybe Text -> Either String a
- Serv.Header: headerEncode :: HeaderEncode n a => Proxy n -> a -> Maybe Text
- Serv.Header.Proxies: Proxy :: Proxy k
- Serv.Header.Proxies: accept :: Proxy Accept
- Serv.Header.Proxies: acceptCharset :: Proxy AcceptCharset
- Serv.Header.Proxies: acceptEncoding :: Proxy AcceptEncoding
- Serv.Header.Proxies: acceptLanguage :: Proxy AcceptLanguage
- Serv.Header.Proxies: acceptPatch :: Proxy AcceptPatch
- Serv.Header.Proxies: acceptRanges :: Proxy AcceptRanges
- Serv.Header.Proxies: accessControlAllowCredentials :: Proxy AccessControlAllowCredentials
- Serv.Header.Proxies: accessControlAllowHeaders :: Proxy AccessControlAllowHeaders
- Serv.Header.Proxies: accessControlAllowMethods :: Proxy AccessControlAllowMethods
- Serv.Header.Proxies: accessControlAllowOrigin :: Proxy AccessControlAllowOrigin
- Serv.Header.Proxies: accessControlExposeHeaders :: Proxy AccessControlExposeHeaders
- Serv.Header.Proxies: accessControlMaxAge :: Proxy AccessControlMaxAge
- Serv.Header.Proxies: accessControlRequestHeaders :: Proxy AccessControlRequestHeaders
- Serv.Header.Proxies: accessControlRequestMethod :: Proxy AccessControlRequestMethod
- Serv.Header.Proxies: age :: Proxy Age
- Serv.Header.Proxies: allow :: Proxy Allow
- Serv.Header.Proxies: authorization :: Proxy Authorization
- Serv.Header.Proxies: cacheControl :: Proxy CacheControl
- Serv.Header.Proxies: connection :: Proxy Connection
- Serv.Header.Proxies: contentDisposition :: Proxy ContentDisposition
- Serv.Header.Proxies: contentEncoding :: Proxy ContentEncoding
- Serv.Header.Proxies: contentLanguage :: Proxy ContentLanguage
- Serv.Header.Proxies: contentLength :: Proxy ContentLength
- Serv.Header.Proxies: contentLocation :: Proxy ContentLocation
- Serv.Header.Proxies: contentRange :: Proxy ContentRange
- Serv.Header.Proxies: contentSecurityPolicy :: Proxy ContentSecurityPolicy
- Serv.Header.Proxies: contentType :: Proxy ContentType
- Serv.Header.Proxies: cookie :: Proxy Cookie
- Serv.Header.Proxies: data Proxy k (t :: k) :: forall k. k -> *
- Serv.Header.Proxies: date :: Proxy Date
- Serv.Header.Proxies: eTag :: Proxy ETag
- Serv.Header.Proxies: expect :: Proxy Expect
- Serv.Header.Proxies: expires :: Proxy Expires
- Serv.Header.Proxies: from :: Proxy From
- Serv.Header.Proxies: host :: Proxy Host
- Serv.Header.Proxies: ifMatch :: Proxy IfMatch
- Serv.Header.Proxies: ifModifiedSince :: Proxy IfModifiedSince
- Serv.Header.Proxies: ifNoneMatch :: Proxy IfNoneMatch
- Serv.Header.Proxies: ifRange :: Proxy IfRange
- Serv.Header.Proxies: ifUnmodifiedSince :: Proxy IfUnmodifiedSince
- Serv.Header.Proxies: lastModified :: Proxy LastModified
- Serv.Header.Proxies: link :: Proxy Link
- Serv.Header.Proxies: location :: Proxy Location
- Serv.Header.Proxies: maxForwards :: Proxy MaxForwards
- Serv.Header.Proxies: origin :: Proxy Origin
- Serv.Header.Proxies: pragma :: Proxy Pragma
- Serv.Header.Proxies: proxyAuthenticate :: Proxy ProxyAuthenticate
- Serv.Header.Proxies: proxyAuthorization :: Proxy ProxyAuthorization
- Serv.Header.Proxies: publicKeyPins :: Proxy PublicKeyPins
- Serv.Header.Proxies: range :: Proxy Range
- Serv.Header.Proxies: referer :: Proxy Referer
- Serv.Header.Proxies: retryAfter :: Proxy RetryAfter
- Serv.Header.Proxies: setCookie :: Proxy SetCookie
- Serv.Header.Proxies: strictTransportSecurity :: Proxy StrictTransportSecurity
- Serv.Header.Proxies: tE :: Proxy TE
- Serv.Header.Proxies: trailer :: Proxy Trailer
- Serv.Header.Proxies: transferEncoding :: Proxy TransferEncoding
- Serv.Header.Proxies: upgrade :: Proxy Upgrade
- Serv.Header.Proxies: userAgent :: Proxy UserAgent
- Serv.Header.Proxies: vary :: Proxy Vary
- Serv.Header.Proxies: via :: Proxy Via
- Serv.Header.Proxies: wWWAuthenticate :: Proxy WWWAuthenticate
- Serv.Header.Proxies: warning :: Proxy Warning
- Serv.Header.Proxies: xCsrfToken :: Proxy XCsrfToken
- Serv.Header.Proxies: xForwardedFor :: Proxy XForwardedFor
- Serv.Header.Proxies: xForwardedHost :: Proxy XForwardedHost
- Serv.Header.Proxies: xForwardedProto :: Proxy XForwardedProto
- Serv.Internal.Api: [:>] :: Path star -> Api star -> Api star
- Serv.Internal.Api: [Body] :: [star] -> star -> Body star
- Serv.Internal.Api: [CaptureBody] :: [star] -> star -> Method star -> Method star
- Serv.Internal.Api: [CaptureHeaders] :: [Pair HeaderName star] -> Method star -> Method star
- Serv.Internal.Api: [CaptureQuery] :: [Pair Symbol star] -> Method star -> Method star
- Serv.Internal.Api: [Const] :: Symbol -> Path star
- Serv.Internal.Api: [Cors] :: star -> Path star
- Serv.Internal.Api: [Empty] :: Body star
- Serv.Internal.Api: [Endpoint] :: [Method star] -> Api star
- Serv.Internal.Api: [Flag] :: Symbol -> Path star
- Serv.Internal.Api: [HeaderAs] :: HeaderName -> Symbol -> Path star
- Serv.Internal.Api: [Header] :: HeaderName -> star -> Path star
- Serv.Internal.Api: [Method] :: Verb -> [Pair HeaderName star] -> Body star -> Method star
- Serv.Internal.Api: [OneOf] :: [Api star] -> Api star
- Serv.Internal.Api: [QueryParam] :: Symbol -> star -> Path star
- Serv.Internal.Api: [Raw] :: Api star
- Serv.Internal.Api: [Seg] :: Symbol -> star -> Path star
- Serv.Internal.Api: [Wildcard] :: Path star
- Serv.Internal.Api: data Api star
- Serv.Internal.Api: data Body star
- Serv.Internal.Api: data Method star
- Serv.Internal.Api: data Path star
- Serv.Internal.Api.Analysis: class HeadersExpectedOf (methods :: [Method *])
- Serv.Internal.Api.Analysis: class HeadersReturnedBy (methods :: [Method *])
- Serv.Internal.Api.Analysis: class VerbsOf methods
- Serv.Internal.Api.Analysis: headersExpectedOf :: HeadersExpectedOf methods => Proxy methods -> Set HeaderName
- Serv.Internal.Api.Analysis: headersReturnedBy :: HeadersReturnedBy methods => Proxy methods -> Set HeaderName
- Serv.Internal.Api.Analysis: instance (Serv.Internal.Api.Analysis.HeadersExpectedOf (method : rs), Serv.Internal.Header.ReflectHeaderNames hdrs) => Serv.Internal.Api.Analysis.HeadersExpectedOf ('Serv.Internal.Api.CaptureHeaders hdrs method : rs)
- Serv.Internal.Api.Analysis: instance (Serv.Internal.Header.ReflectHeaderNames headers, Serv.Internal.Api.Analysis.HeadersReturnedBy rs) => Serv.Internal.Api.Analysis.HeadersReturnedBy ('Serv.Internal.Api.Method verb headers body : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersExpectedOf '[]
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersExpectedOf (method : rs) => Serv.Internal.Api.Analysis.HeadersExpectedOf ('Serv.Internal.Api.CaptureBody ctypes ty method : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersExpectedOf (method : rs) => Serv.Internal.Api.Analysis.HeadersExpectedOf ('Serv.Internal.Api.CaptureQuery names method : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersExpectedOf rs => Serv.Internal.Api.Analysis.HeadersExpectedOf ('Serv.Internal.Api.Method verb headers body : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersReturnedBy '[]
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersReturnedBy (method : rs) => Serv.Internal.Api.Analysis.HeadersReturnedBy ('Serv.Internal.Api.CaptureBody ctypes ty method : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersReturnedBy (method : rs) => Serv.Internal.Api.Analysis.HeadersReturnedBy ('Serv.Internal.Api.CaptureHeaders hdrs method : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.HeadersReturnedBy (method : rs) => Serv.Internal.Api.Analysis.HeadersReturnedBy ('Serv.Internal.Api.CaptureQuery names method : rs)
- Serv.Internal.Api.Analysis: instance Serv.Internal.Api.Analysis.VerbsOf '[]
- Serv.Internal.Api.Analysis: instance forall star (verb :: Serv.Internal.Verb.Verb) (methods :: [Serv.Internal.Api.Method star]) (headers :: [Serv.Internal.Pair.Pair Serv.Internal.Header.Name.HeaderName star]) (body :: Serv.Internal.Api.Body star). (Serv.Internal.Verb.ReflectVerb verb, Serv.Internal.Api.Analysis.VerbsOf methods) => Serv.Internal.Api.Analysis.VerbsOf ('Serv.Internal.Api.Method verb headers body : methods)
- Serv.Internal.Api.Analysis: verbsOf :: VerbsOf methods => Proxy methods -> Set Verb
- Serv.Internal.Cors: AccessSet :: Bool -> Set HeaderName -> Bool -> Set Verb -> Set HeaderName -> Maybe NominalDiffTime -> AccessSet
- Serv.Internal.Cors: Context :: Text -> Set HeaderName -> Set HeaderName -> Set Verb -> Context
- Serv.Internal.Cors: [credentialsAllowed] :: AccessSet -> Bool
- Serv.Internal.Cors: [headersAllowed] :: AccessSet -> Set HeaderName
- Serv.Internal.Cors: [headersExpected] :: Context -> Set HeaderName
- Serv.Internal.Cors: [headersExposed] :: AccessSet -> Set HeaderName
- Serv.Internal.Cors: [headersReturned] :: Context -> Set HeaderName
- Serv.Internal.Cors: [maxAge] :: AccessSet -> Maybe NominalDiffTime
- Serv.Internal.Cors: [methodsAllowed] :: AccessSet -> Set Verb
- Serv.Internal.Cors: [methodsAvailable] :: Context -> Set Verb
- Serv.Internal.Cors: [originAllowed] :: AccessSet -> Bool
- Serv.Internal.Cors: [origin] :: Context -> Text
- Serv.Internal.Cors: class CorsPolicy m
- Serv.Internal.Cors: corsPolicy :: CorsPolicy m => Proxy m -> Policy
- Serv.Internal.Cors: data AccessSet
- Serv.Internal.Cors: data Context
- Serv.Internal.Cors: data PermitAll
- Serv.Internal.Cors: headerSet :: Bool -> Context -> AccessSet -> [Header]
- Serv.Internal.Cors: instance GHC.Base.Monoid Serv.Internal.Cors.AccessSet
- Serv.Internal.Cors: instance Serv.Internal.Cors.CorsPolicy Serv.Internal.Cors.PermitAll
- Serv.Internal.Cors: mergeContext :: Context -> Context -> Context
- Serv.Internal.Cors: permitAll :: Policy
- Serv.Internal.Cors: predicateWhitelist :: (Text -> Bool) -> Policy
- Serv.Internal.Cors: type Policy = Config -> Context -> AccessSet
- Serv.Internal.Cors: wildcard :: Policy
- Serv.Internal.Header: Accept :: HeaderName
- Serv.Internal.Header: AcceptCharset :: HeaderName
- Serv.Internal.Header: AcceptEncoding :: HeaderName
- Serv.Internal.Header: AcceptLanguage :: HeaderName
- Serv.Internal.Header: AcceptPatch :: HeaderName
- Serv.Internal.Header: AcceptRanges :: HeaderName
- Serv.Internal.Header: AccessControlAllowCredentials :: HeaderName
- Serv.Internal.Header: AccessControlAllowHeaders :: HeaderName
- Serv.Internal.Header: AccessControlAllowMethods :: HeaderName
- Serv.Internal.Header: AccessControlAllowOrigin :: HeaderName
- Serv.Internal.Header: AccessControlExposeHeaders :: HeaderName
- Serv.Internal.Header: AccessControlMaxAge :: HeaderName
- Serv.Internal.Header: AccessControlRequestHeaders :: HeaderName
- Serv.Internal.Header: AccessControlRequestMethod :: HeaderName
- Serv.Internal.Header: Age :: HeaderName
- Serv.Internal.Header: Allow :: HeaderName
- Serv.Internal.Header: Authorization :: HeaderName
- Serv.Internal.Header: CacheControl :: HeaderName
- Serv.Internal.Header: Connection :: HeaderName
- Serv.Internal.Header: ContentDisposition :: HeaderName
- Serv.Internal.Header: ContentEncoding :: HeaderName
- Serv.Internal.Header: ContentLanguage :: HeaderName
- Serv.Internal.Header: ContentLength :: HeaderName
- Serv.Internal.Header: ContentLocation :: HeaderName
- Serv.Internal.Header: ContentRange :: HeaderName
- Serv.Internal.Header: ContentSecurityPolicy :: HeaderName
- Serv.Internal.Header: ContentType :: HeaderName
- Serv.Internal.Header: Cookie :: HeaderName
- Serv.Internal.Header: Date :: HeaderName
- Serv.Internal.Header: ETag :: HeaderName
- Serv.Internal.Header: Expect :: HeaderName
- Serv.Internal.Header: Expires :: HeaderName
- Serv.Internal.Header: From :: HeaderName
- Serv.Internal.Header: HeaderName :: Symbol -> HeaderName
- Serv.Internal.Header: Host :: HeaderName
- Serv.Internal.Header: IfMatch :: HeaderName
- Serv.Internal.Header: IfModifiedSince :: HeaderName
- Serv.Internal.Header: IfNoneMatch :: HeaderName
- Serv.Internal.Header: IfRange :: HeaderName
- Serv.Internal.Header: IfUnmodifiedSince :: HeaderName
- Serv.Internal.Header: LastModified :: HeaderName
- Serv.Internal.Header: Link :: HeaderName
- Serv.Internal.Header: Location :: HeaderName
- Serv.Internal.Header: MaxForwards :: HeaderName
- Serv.Internal.Header: Origin :: HeaderName
- Serv.Internal.Header: Pragma :: HeaderName
- Serv.Internal.Header: ProxyAuthenticate :: HeaderName
- Serv.Internal.Header: ProxyAuthorization :: HeaderName
- Serv.Internal.Header: PublicKeyPins :: HeaderName
- Serv.Internal.Header: Range :: HeaderName
- Serv.Internal.Header: Referer :: HeaderName
- Serv.Internal.Header: RetryAfter :: HeaderName
- Serv.Internal.Header: SetCookie :: HeaderName
- Serv.Internal.Header: StrictTransportSecurity :: HeaderName
- Serv.Internal.Header: TE :: HeaderName
- Serv.Internal.Header: Trailer :: HeaderName
- Serv.Internal.Header: TransferEncoding :: HeaderName
- Serv.Internal.Header: Upgrade :: HeaderName
- Serv.Internal.Header: UserAgent :: HeaderName
- Serv.Internal.Header: Vary :: HeaderName
- Serv.Internal.Header: Via :: HeaderName
- Serv.Internal.Header: WWWAuthenticate :: HeaderName
- Serv.Internal.Header: Warning :: HeaderName
- Serv.Internal.Header: XCsrfToken :: HeaderName
- Serv.Internal.Header: XForwardedFor :: HeaderName
- Serv.Internal.Header: XForwardedHost :: HeaderName
- Serv.Internal.Header: XForwardedProto :: HeaderName
- Serv.Internal.Header: class ReflectName n => HeaderDecode (n :: HeaderName) a
- Serv.Internal.Header: class ReflectName n => HeaderEncode (n :: HeaderName) a
- Serv.Internal.Header: class ReflectHeaderNames headers
- Serv.Internal.Header: class ReflectHeaders headers
- Serv.Internal.Header: class ReflectName (n :: HeaderName)
- Serv.Internal.Header: data HeaderName
- Serv.Internal.Header: headerDecode :: HeaderDecode n a => Proxy n -> Maybe Text -> Either String a
- Serv.Internal.Header: headerDecodeRaw :: HeaderDecode n a => Proxy n -> Maybe ByteString -> Either String a
- Serv.Internal.Header: headerEncode :: HeaderEncode n a => Proxy n -> a -> Maybe Text
- Serv.Internal.Header: headerEncodeRaw :: HeaderEncode n a => Proxy n -> a -> Maybe ByteString
- Serv.Internal.Header: headerPair :: HeaderEncode h v => Proxy h -> v -> Maybe Header
- Serv.Internal.Header: instance (Serv.Internal.Header.Name.ReflectName name, Serv.Internal.Header.Serialization.HeaderEncode name ty, Serv.Internal.Header.ReflectHeaders headers) => Serv.Internal.Header.ReflectHeaders (name 'Serv.Internal.Pair.::: ty : headers)
- Serv.Internal.Header: instance Serv.Internal.Header.ReflectHeaderNames '[]
- Serv.Internal.Header: instance Serv.Internal.Header.ReflectHeaders '[]
- Serv.Internal.Header: instance forall b (name :: Serv.Internal.Header.Name.HeaderName) (hdrs :: [Serv.Internal.Pair.Pair Serv.Internal.Header.Name.HeaderName b]) (ty :: b). (Serv.Internal.Header.Name.ReflectName name, Serv.Internal.Header.ReflectHeaderNames hdrs) => Serv.Internal.Header.ReflectHeaderNames (name 'Serv.Internal.Pair.::: ty : hdrs)
- Serv.Internal.Header: reflectHeaderNames :: ReflectHeaderNames headers => Proxy headers -> [HeaderName]
- Serv.Internal.Header: reflectHeaders :: ReflectHeaders headers => Rec headers -> [Header]
- Serv.Internal.Header: reflectName :: ReflectName n => proxy n -> HeaderName
- Serv.Internal.Header.Name: Accept :: HeaderName
- Serv.Internal.Header.Name: AcceptCharset :: HeaderName
- Serv.Internal.Header.Name: AcceptEncoding :: HeaderName
- Serv.Internal.Header.Name: AcceptLanguage :: HeaderName
- Serv.Internal.Header.Name: AcceptPatch :: HeaderName
- Serv.Internal.Header.Name: AcceptRanges :: HeaderName
- Serv.Internal.Header.Name: AccessControlAllowCredentials :: HeaderName
- Serv.Internal.Header.Name: AccessControlAllowHeaders :: HeaderName
- Serv.Internal.Header.Name: AccessControlAllowMethods :: HeaderName
- Serv.Internal.Header.Name: AccessControlAllowOrigin :: HeaderName
- Serv.Internal.Header.Name: AccessControlExposeHeaders :: HeaderName
- Serv.Internal.Header.Name: AccessControlMaxAge :: HeaderName
- Serv.Internal.Header.Name: AccessControlRequestHeaders :: HeaderName
- Serv.Internal.Header.Name: AccessControlRequestMethod :: HeaderName
- Serv.Internal.Header.Name: Age :: HeaderName
- Serv.Internal.Header.Name: Allow :: HeaderName
- Serv.Internal.Header.Name: Authorization :: HeaderName
- Serv.Internal.Header.Name: CacheControl :: HeaderName
- Serv.Internal.Header.Name: Connection :: HeaderName
- Serv.Internal.Header.Name: ContentDisposition :: HeaderName
- Serv.Internal.Header.Name: ContentEncoding :: HeaderName
- Serv.Internal.Header.Name: ContentLanguage :: HeaderName
- Serv.Internal.Header.Name: ContentLength :: HeaderName
- Serv.Internal.Header.Name: ContentLocation :: HeaderName
- Serv.Internal.Header.Name: ContentRange :: HeaderName
- Serv.Internal.Header.Name: ContentSecurityPolicy :: HeaderName
- Serv.Internal.Header.Name: ContentType :: HeaderName
- Serv.Internal.Header.Name: Cookie :: HeaderName
- Serv.Internal.Header.Name: Date :: HeaderName
- Serv.Internal.Header.Name: ETag :: HeaderName
- Serv.Internal.Header.Name: Expect :: HeaderName
- Serv.Internal.Header.Name: Expires :: HeaderName
- Serv.Internal.Header.Name: From :: HeaderName
- Serv.Internal.Header.Name: HeaderName :: Symbol -> HeaderName
- Serv.Internal.Header.Name: Host :: HeaderName
- Serv.Internal.Header.Name: IfMatch :: HeaderName
- Serv.Internal.Header.Name: IfModifiedSince :: HeaderName
- Serv.Internal.Header.Name: IfNoneMatch :: HeaderName
- Serv.Internal.Header.Name: IfRange :: HeaderName
- Serv.Internal.Header.Name: IfUnmodifiedSince :: HeaderName
- Serv.Internal.Header.Name: LastModified :: HeaderName
- Serv.Internal.Header.Name: Link :: HeaderName
- Serv.Internal.Header.Name: Location :: HeaderName
- Serv.Internal.Header.Name: MaxForwards :: HeaderName
- Serv.Internal.Header.Name: Origin :: HeaderName
- Serv.Internal.Header.Name: Pragma :: HeaderName
- Serv.Internal.Header.Name: ProxyAuthenticate :: HeaderName
- Serv.Internal.Header.Name: ProxyAuthorization :: HeaderName
- Serv.Internal.Header.Name: PublicKeyPins :: HeaderName
- Serv.Internal.Header.Name: Range :: HeaderName
- Serv.Internal.Header.Name: Referer :: HeaderName
- Serv.Internal.Header.Name: RetryAfter :: HeaderName
- Serv.Internal.Header.Name: SetCookie :: HeaderName
- Serv.Internal.Header.Name: StrictTransportSecurity :: HeaderName
- Serv.Internal.Header.Name: TE :: HeaderName
- Serv.Internal.Header.Name: Trailer :: HeaderName
- Serv.Internal.Header.Name: TransferEncoding :: HeaderName
- Serv.Internal.Header.Name: Upgrade :: HeaderName
- Serv.Internal.Header.Name: UserAgent :: HeaderName
- Serv.Internal.Header.Name: Vary :: HeaderName
- Serv.Internal.Header.Name: Via :: HeaderName
- Serv.Internal.Header.Name: WWWAuthenticate :: HeaderName
- Serv.Internal.Header.Name: Warning :: HeaderName
- Serv.Internal.Header.Name: XCsrfToken :: HeaderName
- Serv.Internal.Header.Name: XForwardedFor :: HeaderName
- Serv.Internal.Header.Name: XForwardedHost :: HeaderName
- Serv.Internal.Header.Name: XForwardedProto :: HeaderName
- Serv.Internal.Header.Name: accept :: Proxy Accept
- Serv.Internal.Header.Name: acceptCharset :: Proxy AcceptCharset
- Serv.Internal.Header.Name: acceptEncoding :: Proxy AcceptEncoding
- Serv.Internal.Header.Name: acceptLanguage :: Proxy AcceptLanguage
- Serv.Internal.Header.Name: acceptPatch :: Proxy AcceptPatch
- Serv.Internal.Header.Name: acceptRanges :: Proxy AcceptRanges
- Serv.Internal.Header.Name: accessControlAllowCredentials :: Proxy AccessControlAllowCredentials
- Serv.Internal.Header.Name: accessControlAllowHeaders :: Proxy AccessControlAllowHeaders
- Serv.Internal.Header.Name: accessControlAllowMethods :: Proxy AccessControlAllowMethods
- Serv.Internal.Header.Name: accessControlAllowOrigin :: Proxy AccessControlAllowOrigin
- Serv.Internal.Header.Name: accessControlExposeHeaders :: Proxy AccessControlExposeHeaders
- Serv.Internal.Header.Name: accessControlMaxAge :: Proxy AccessControlMaxAge
- Serv.Internal.Header.Name: accessControlRequestHeaders :: Proxy AccessControlRequestHeaders
- Serv.Internal.Header.Name: accessControlRequestMethod :: Proxy AccessControlRequestMethod
- Serv.Internal.Header.Name: age :: Proxy Age
- Serv.Internal.Header.Name: allow :: Proxy Allow
- Serv.Internal.Header.Name: authorization :: Proxy Authorization
- Serv.Internal.Header.Name: cacheControl :: Proxy CacheControl
- Serv.Internal.Header.Name: class ReflectName (n :: HeaderName)
- Serv.Internal.Header.Name: connection :: Proxy Connection
- Serv.Internal.Header.Name: contentDisposition :: Proxy ContentDisposition
- Serv.Internal.Header.Name: contentEncoding :: Proxy ContentEncoding
- Serv.Internal.Header.Name: contentLanguage :: Proxy ContentLanguage
- Serv.Internal.Header.Name: contentLength :: Proxy ContentLength
- Serv.Internal.Header.Name: contentLocation :: Proxy ContentLocation
- Serv.Internal.Header.Name: contentRange :: Proxy ContentRange
- Serv.Internal.Header.Name: contentSecurityPolicy :: Proxy ContentSecurityPolicy
- Serv.Internal.Header.Name: contentType :: Proxy ContentType
- Serv.Internal.Header.Name: cookie :: Proxy Cookie
- Serv.Internal.Header.Name: data HeaderName
- Serv.Internal.Header.Name: date :: Proxy Date
- Serv.Internal.Header.Name: eTag :: Proxy ETag
- Serv.Internal.Header.Name: expect :: Proxy Expect
- Serv.Internal.Header.Name: expires :: Proxy Expires
- Serv.Internal.Header.Name: from :: Proxy From
- Serv.Internal.Header.Name: host :: Proxy Host
- Serv.Internal.Header.Name: ifMatch :: Proxy IfMatch
- Serv.Internal.Header.Name: ifModifiedSince :: Proxy IfModifiedSince
- Serv.Internal.Header.Name: ifNoneMatch :: Proxy IfNoneMatch
- Serv.Internal.Header.Name: ifRange :: Proxy IfRange
- Serv.Internal.Header.Name: ifUnmodifiedSince :: Proxy IfUnmodifiedSince
- Serv.Internal.Header.Name: instance GHC.TypeLits.KnownSymbol s => Serv.Internal.Header.Name.ReflectName ('Serv.Internal.Header.Name.HeaderName s)
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Accept
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AcceptCharset
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AcceptEncoding
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AcceptLanguage
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AcceptPatch
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AcceptRanges
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlAllowCredentials
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlAllowHeaders
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlAllowMethods
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlAllowOrigin
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlExposeHeaders
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlMaxAge
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlRequestHeaders
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.AccessControlRequestMethod
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Age
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Allow
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Authorization
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.CacheControl
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Connection
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentDisposition
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentEncoding
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentLanguage
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentLength
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentLocation
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentRange
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentSecurityPolicy
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ContentType
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Cookie
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Date
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ETag
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Expect
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Expires
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.From
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Host
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.IfMatch
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.IfModifiedSince
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.IfNoneMatch
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.IfRange
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.IfUnmodifiedSince
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.LastModified
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Link
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Location
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.MaxForwards
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Origin
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Pragma
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ProxyAuthenticate
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.ProxyAuthorization
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.PublicKeyPins
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Range
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Referer
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.RetryAfter
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.SetCookie
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.StrictTransportSecurity
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.TE
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Trailer
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.TransferEncoding
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Upgrade
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.UserAgent
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Vary
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Via
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.WWWAuthenticate
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.Warning
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.XCsrfToken
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.XForwardedFor
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.XForwardedHost
- Serv.Internal.Header.Name: instance Serv.Internal.Header.Name.ReflectName 'Serv.Internal.Header.Name.XForwardedProto
- Serv.Internal.Header.Name: lastModified :: Proxy LastModified
- Serv.Internal.Header.Name: link :: Proxy Link
- Serv.Internal.Header.Name: location :: Proxy Location
- Serv.Internal.Header.Name: maxForwards :: Proxy MaxForwards
- Serv.Internal.Header.Name: origin :: Proxy Origin
- Serv.Internal.Header.Name: pragma :: Proxy Pragma
- Serv.Internal.Header.Name: proxyAuthenticate :: Proxy ProxyAuthenticate
- Serv.Internal.Header.Name: proxyAuthorization :: Proxy ProxyAuthorization
- Serv.Internal.Header.Name: publicKeyPins :: Proxy PublicKeyPins
- Serv.Internal.Header.Name: range :: Proxy Range
- Serv.Internal.Header.Name: referer :: Proxy Referer
- Serv.Internal.Header.Name: reflectName :: ReflectName n => proxy n -> HeaderName
- Serv.Internal.Header.Name: retryAfter :: Proxy RetryAfter
- Serv.Internal.Header.Name: setCookie :: Proxy SetCookie
- Serv.Internal.Header.Name: strictTransportSecurity :: Proxy StrictTransportSecurity
- Serv.Internal.Header.Name: tE :: Proxy TE
- Serv.Internal.Header.Name: trailer :: Proxy Trailer
- Serv.Internal.Header.Name: transferEncoding :: Proxy TransferEncoding
- Serv.Internal.Header.Name: upgrade :: Proxy Upgrade
- Serv.Internal.Header.Name: userAgent :: Proxy UserAgent
- Serv.Internal.Header.Name: vary :: Proxy Vary
- Serv.Internal.Header.Name: via :: Proxy Via
- Serv.Internal.Header.Name: wWWAuthenticate :: Proxy WWWAuthenticate
- Serv.Internal.Header.Name: warning :: Proxy Warning
- Serv.Internal.Header.Name: xCsrfToken :: Proxy XCsrfToken
- Serv.Internal.Header.Name: xForwardedFor :: Proxy XForwardedFor
- Serv.Internal.Header.Name: xForwardedHost :: Proxy XForwardedHost
- Serv.Internal.Header.Name: xForwardedProto :: Proxy XForwardedProto
- Serv.Internal.Header.Serialization: class ReflectName n => HeaderDecode (n :: HeaderName) a
- Serv.Internal.Header.Serialization: class ReflectName n => HeaderEncode (n :: HeaderName) a
- Serv.Internal.Header.Serialization: headerDecode :: HeaderDecode n a => Proxy n -> Maybe Text -> Either String a
- Serv.Internal.Header.Serialization: headerDecode' :: HeaderDecode n a => Proxy n -> Text -> Either String a
- Serv.Internal.Header.Serialization: headerDecodeRaw :: HeaderDecode n a => Proxy n -> Maybe ByteString -> Either String a
- Serv.Internal.Header.Serialization: headerEncode :: HeaderEncode n a => Proxy n -> a -> Maybe Text
- Serv.Internal.Header.Serialization: headerEncodeRaw :: HeaderEncode n a => Proxy n -> a -> Maybe ByteString
- Serv.Internal.Header.Serialization: headerPair :: HeaderEncode h v => Proxy h -> v -> Maybe Header
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Name.ReflectName n => Serv.Internal.Header.Serialization.HeaderDecode n Serv.Internal.RawText.RawText
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Name.ReflectName n => Serv.Internal.Header.Serialization.HeaderEncode n Data.Text.Internal.Text
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Name.ReflectName n => Serv.Internal.Header.Serialization.HeaderEncode n GHC.Types.Bool
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Name.ReflectName n => Serv.Internal.Header.Serialization.HeaderEncode n GHC.Types.Int
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Name.ReflectName n => Serv.Internal.Header.Serialization.HeaderEncode n Serv.Internal.RawText.RawText
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderDecode 'Serv.Internal.Header.Name.Accept [Network.HTTP.Media.Quality.Quality Network.HTTP.Media.MediaType.Internal.MediaType]
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderDecode h t => Serv.Internal.Header.Serialization.HeaderDecode h (GHC.Base.Maybe t)
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlAllowCredentials GHC.Types.Bool
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlAllowHeaders (Data.Set.Base.Set Network.HTTP.Types.Header.HeaderName)
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlAllowMethods (Data.Set.Base.Set Serv.Internal.Verb.Verb)
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlAllowMethods [Serv.Internal.Verb.Verb]
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlAllowOrigin Data.Text.Internal.Text
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlExposeHeaders (Data.Set.Base.Set Network.HTTP.Types.Header.HeaderName)
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.AccessControlMaxAge Data.Time.Clock.UTC.NominalDiffTime
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.Allow (Data.Set.Base.Set Serv.Internal.Verb.Verb)
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode 'Serv.Internal.Header.Name.Allow [Serv.Internal.Verb.Verb]
- Serv.Internal.Header.Serialization: instance Serv.Internal.Header.Serialization.HeaderEncode h t => Serv.Internal.Header.Serialization.HeaderEncode h (GHC.Base.Maybe t)
- Serv.Internal.Header.Serialization: required :: (Text -> Either String a) -> Maybe Text -> Either String a
- Serv.Internal.MediaType: class HasMediaType ty
- Serv.Internal.MediaType: class HasMediaType ty => MimeDecode ty val
- Serv.Internal.MediaType: class HasMediaType ty => MimeEncode ty val
- Serv.Internal.MediaType: class ReflectDecoders cts ty
- Serv.Internal.MediaType: class ReflectEncoders cts ty
- Serv.Internal.MediaType: instance Serv.Internal.MediaType.ReflectDecoders '[] ty
- Serv.Internal.MediaType: instance Serv.Internal.MediaType.ReflectEncoders '[] ty
- Serv.Internal.MediaType: instance forall a (ct :: a) ty (cts :: [a]). (Serv.Internal.MediaType.MimeDecode ct ty, Serv.Internal.MediaType.ReflectDecoders cts ty) => Serv.Internal.MediaType.ReflectDecoders (ct : cts) ty
- Serv.Internal.MediaType: instance forall a (cts :: [a]) ty (ct :: a). (Serv.Internal.MediaType.ReflectEncoders cts ty, Serv.Internal.MediaType.MimeEncode ct ty) => Serv.Internal.MediaType.ReflectEncoders (ct : cts) ty
- Serv.Internal.MediaType: mediaType :: HasMediaType ty => Proxy ty -> MediaType
- Serv.Internal.MediaType: mimeDecode :: MimeDecode ty val => Proxy ty -> ByteString -> Either String val
- Serv.Internal.MediaType: mimeEncode :: MimeEncode ty val => Proxy ty -> val -> ByteString
- Serv.Internal.MediaType: negotiateContent :: ReflectEncoders ctypes a => Proxy ctypes -> [Quality MediaType] -> a -> Maybe (MediaType, ByteString)
- Serv.Internal.MediaType: negotiateContentAlways :: ReflectEncoders ctypes a => Proxy ctypes -> [Quality MediaType] -> a -> Maybe (MediaType, ByteString)
- Serv.Internal.MediaType: reflectDecoders :: ReflectDecoders cts ty => Proxy cts -> [(MediaType, ByteString -> Either String ty)]
- Serv.Internal.MediaType: reflectEncoders :: ReflectEncoders cts ty => Proxy cts -> [(MediaType, ty -> ByteString)]
- Serv.Internal.MediaType: tryDecode :: ReflectDecoders ctypes a => Proxy ctypes -> ByteString -> ByteString -> Maybe (Either String a)
- Serv.Internal.Pair: (:::) :: a -> b -> Pair a b
- Serv.Internal.Pair: data Pair a b
- Serv.Internal.Query: class QueryDecode (s :: Symbol) a
- Serv.Internal.Query: class QueryEncode (s :: Symbol) a
- Serv.Internal.Query: class ReflectQuery query
- Serv.Internal.Query: instance (GHC.TypeLits.KnownSymbol s, Serv.Internal.Query.QueryEncode s a, Serv.Internal.Query.ReflectQuery query) => Serv.Internal.Query.ReflectQuery (s 'Serv.Internal.Pair.::: a : query)
- Serv.Internal.Query: instance Serv.Internal.Query.QueryDecode s Serv.Internal.RawText.RawText
- Serv.Internal.Query: instance Serv.Internal.Query.QueryEncode s Serv.Internal.RawText.RawText
- Serv.Internal.Query: instance Serv.Internal.Query.ReflectQuery '[]
- Serv.Internal.Query: queryDecode :: QueryDecode s a => Proxy s -> Maybe Text -> Either String a
- Serv.Internal.Query: queryEncode :: QueryEncode s a => Proxy s -> a -> Maybe Text
- Serv.Internal.Query: reflectQuery :: ReflectQuery query => Rec query -> Query
- Serv.Internal.RawText: RawText :: Text -> RawText
- Serv.Internal.RawText: [getRawText] :: RawText -> Text
- Serv.Internal.RawText: instance Data.String.IsString Serv.Internal.RawText.RawText
- Serv.Internal.RawText: instance GHC.Base.Monoid Serv.Internal.RawText.RawText
- Serv.Internal.RawText: instance GHC.Classes.Eq Serv.Internal.RawText.RawText
- Serv.Internal.RawText: instance GHC.Classes.Ord Serv.Internal.RawText.RawText
- Serv.Internal.RawText: instance GHC.Read.Read Serv.Internal.RawText.RawText
- Serv.Internal.RawText: instance GHC.Show.Show Serv.Internal.RawText.RawText
- Serv.Internal.RawText: newtype RawText
- Serv.Internal.Rec: (-:) :: Proxy name -> ty -> Rec rs -> Rec ((name ::: ty) : rs)
- Serv.Internal.Rec: [Cons] :: ty -> Rec rs -> Rec ((name ::: ty) : rs)
- Serv.Internal.Rec: [Nil] :: Rec '[]
- Serv.Internal.Rec: class Elem name e es
- Serv.Internal.Rec: class RecordIso rs qs
- Serv.Internal.Rec: class Subset rs qs
- Serv.Internal.Rec: data Rec rs
- Serv.Internal.Rec: eGet :: Elem name e es => Rec es -> Tagged name e
- Serv.Internal.Rec: eMap :: Elem name e es => Tagged name (e -> e) -> Rec es -> Rec es
- Serv.Internal.Rec: instance forall a (name :: a) e (rs :: [Serv.Internal.Pair.Pair a *]). Serv.Internal.Rec.Elem name e (name 'Serv.Internal.Pair.::: e : rs)
- Serv.Internal.Rec: instance forall a a1 (name :: a1) r (qs :: [Serv.Internal.Pair.Pair a *]) (rs :: [Serv.Internal.Pair.Pair a1 *]). (Serv.Internal.Rec.Elem name r qs, Serv.Internal.Rec.Subset rs qs) => Serv.Internal.Rec.Subset (name 'Serv.Internal.Pair.::: r : rs) qs
- Serv.Internal.Rec: instance forall a a1 (qs :: [Serv.Internal.Pair.Pair a1 *]). Serv.Internal.Rec.Subset '[] qs
- Serv.Internal.Rec: instance forall a a1 (rs :: [Serv.Internal.Pair.Pair a1 *]) (qs :: [Serv.Internal.Pair.Pair a *]). (Serv.Internal.Rec.Subset rs qs, Serv.Internal.Rec.Subset qs rs) => Serv.Internal.Rec.RecordIso rs qs
- Serv.Internal.Rec: instance forall a k (name :: k) e (rs :: [Serv.Internal.Pair.Pair a *]) (r :: Serv.Internal.Pair.Pair a *). Serv.Internal.Rec.Elem name e rs => Serv.Internal.Rec.Elem name e (r : rs)
- Serv.Internal.Rec: project :: Subset rs qs => Rec qs -> Rec rs
- Serv.Internal.Rec: reorder :: RecordIso rs qs => Rec rs -> Rec qs
- Serv.Internal.Server: class Handling (spec :: k) where type Impl spec (m :: * -> *) where {
- Serv.Internal.Server: defaultOptionsResponse :: Set Verb -> ServerValue
- Serv.Internal.Server: encodeBody :: WaiResponse hdrs body => Context -> Response hdrs body -> ServerValue
- Serv.Internal.Server: handle :: (Handling spec, Monad m) => Proxy spec -> Impl spec m -> Server m
- Serv.Internal.Server: instance (Serv.Internal.Api.Analysis.VerbsOf methods, Serv.Internal.Api.Analysis.HeadersReturnedBy methods, Serv.Internal.Api.Analysis.HeadersExpectedOf methods, Serv.Internal.Server.Handling methods) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Endpoint methods)
- Serv.Internal.Server: instance (Serv.Internal.Header.Serialization.HeaderDecode n v, Serv.Internal.Server.Handling api) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Header n v 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: instance (Serv.Internal.Server.Handling api, Serv.Internal.Cors.CorsPolicy p) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Cors p 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: instance (Serv.Internal.URI.URIDecode v, Serv.Internal.Server.Handling api) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Seg n v 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: instance (Serv.Internal.Verb.ReflectVerb verb, Serv.Internal.Server.Type.WaiResponse headers body) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Method verb headers body)
- Serv.Internal.Server: instance Serv.Internal.Server.Handling 'Serv.Internal.Api.Raw
- Serv.Internal.Server: instance Serv.Internal.Server.Handling '[]
- Serv.Internal.Server: instance Serv.Internal.Server.Handling method => Serv.Internal.Server.Handling ('Serv.Internal.Api.CaptureBody ctypes value method)
- Serv.Internal.Server: instance Serv.Internal.Server.Handling method => Serv.Internal.Server.Handling ('Serv.Internal.Api.CaptureHeaders headers method)
- Serv.Internal.Server: instance Serv.Internal.Server.Handling method => Serv.Internal.Server.Handling ('Serv.Internal.Api.CaptureQuery query method)
- Serv.Internal.Server: instance Serv.Internal.Server.Type.WaiResponse headers body => Serv.Internal.Server.Handling ('Serv.Internal.Api.Method 'Serv.Internal.Verb.GET headers body)
- Serv.Internal.Server: instance forall a (x :: a) (xs :: [a]). (Serv.Internal.Server.Handling x, Serv.Internal.Server.Handling xs) => Serv.Internal.Server.Handling (x : xs)
- Serv.Internal.Server: instance forall star (api :: Serv.Internal.Api.Api star). Serv.Internal.Server.Handling api => Serv.Internal.Server.Handling ('Serv.Internal.Api.Wildcard 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: instance forall star (apis :: [Serv.Internal.Api.Api star]). Serv.Internal.Server.Handling apis => Serv.Internal.Server.Handling ('Serv.Internal.Api.OneOf apis)
- Serv.Internal.Server: instance forall star (n :: Serv.Internal.Header.Name.HeaderName) (v :: GHC.Types.Symbol) (api :: Serv.Internal.Api.Api star). (Serv.Internal.Header.Name.ReflectName n, GHC.TypeLits.KnownSymbol v, Serv.Internal.Server.Handling api) => Serv.Internal.Server.Handling ('Serv.Internal.Api.HeaderAs n v 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: instance forall star (s :: GHC.Types.Symbol) (api :: Serv.Internal.Api.Api star). (GHC.TypeLits.KnownSymbol s, Serv.Internal.Server.Handling api) => Serv.Internal.Server.Handling ('Serv.Internal.Api.Const s 'Serv.Internal.Api.:> api)
- Serv.Internal.Server: type family Impl spec (m :: * -> *);
- Serv.Internal.Server: verbMatch :: Set Verb -> Method -> Bool
- Serv.Internal.Server: }
- Serv.Internal.Server.Config: Config :: Config
- Serv.Internal.Server.Config: data Config
- Serv.Internal.Server.Config: defaultConfig :: Config
- Serv.Internal.Server.Context: Context :: Request -> ([Text], [Text]) -> [(HeaderName, Maybe Text)] -> Config -> ByteString -> [Policy] -> Context
- Serv.Internal.Server.Context: [body] :: Context -> ByteString
- Serv.Internal.Server.Context: [config] :: Context -> Config
- Serv.Internal.Server.Context: [corsPolicies] :: Context -> [Policy]
- Serv.Internal.Server.Context: [headersExpected] :: Context -> [(HeaderName, Maybe Text)]
- Serv.Internal.Server.Context: [pathZipper] :: Context -> ([Text], [Text])
- Serv.Internal.Server.Context: [request] :: Context -> Request
- Serv.Internal.Server.Context: corsHeaders :: (HeadersExpectedOf methods, HeadersReturnedBy methods, VerbsOf methods) => Proxy methods -> Bool -> Context -> Maybe [Header]
- Serv.Internal.Server.Context: data Context
- Serv.Internal.Server.Context: examineHeader :: HeaderDecode n a => Proxy n -> Context -> (Context, Either String a)
- Serv.Internal.Server.Context: examineHeaderFast :: HeaderDecode n a => Proxy n -> Context -> Maybe a
- Serv.Internal.Server.Context: expectHeader :: ReflectName n => Proxy n -> Text -> Context -> (Context, Bool)
- Serv.Internal.Server.Context: makeContext :: Config -> Request -> IO Context
- Serv.Internal.Server.Context: method :: Context -> Method
- Serv.Internal.Server.Context: pathIsEmpty :: Context -> Bool
- Serv.Internal.Server.Context: pullHeaderRaw :: HeaderName -> Context -> (Context, Maybe ByteString)
- Serv.Internal.Server.Context: requestHeadersSeen :: Context -> Set HeaderName
- Serv.Internal.Server.Context: safeHead :: [a] -> Maybe a
- Serv.Internal.Server.Context: stepContext :: Context -> Context
- Serv.Internal.Server.Context: takeAllSegments :: Context -> (Context, [Text])
- Serv.Internal.Server.Context: takeSegment :: Context -> (Context, Maybe Text)
- Serv.Internal.Server.Error: BadRequest :: (Maybe String) -> RoutingError
- Serv.Internal.Server.Error: MethodNotAllowed :: [Verb] -> RoutingError
- Serv.Internal.Server.Error: NotFound :: RoutingError
- Serv.Internal.Server.Error: UnsupportedMediaType :: RoutingError
- Serv.Internal.Server.Error: data RoutingError
- Serv.Internal.Server.Error: ignorable :: RoutingError -> Bool
- Serv.Internal.Server.Type: (:<|>) :: a -> b -> (:<|>) a b
- Serv.Internal.Server.Type: Application :: Application -> ServerValue
- Serv.Internal.Server.Type: NotHere :: NotHere
- Serv.Internal.Server.Type: RoutingError :: RoutingError -> ServerValue
- Serv.Internal.Server.Type: Server :: (Context -> m ServerValue) -> Server m
- Serv.Internal.Server.Type: WaiResponse :: Response -> ServerValue
- Serv.Internal.Server.Type: [EmptyResponse] :: Status -> [Header] -> Rec headers -> Response headers Empty
- Serv.Internal.Server.Type: [Response] :: Status -> [Header] -> Rec headers -> a -> Response headers (Body ctypes a)
- Serv.Internal.Server.Type: [runServer] :: Server m -> Context -> m ServerValue
- Serv.Internal.Server.Type: class ReflectHeaders headers => WaiResponse headers body
- Serv.Internal.Server.Type: data (:<|>) a b
- Serv.Internal.Server.Type: data NotHere
- Serv.Internal.Server.Type: data Response (headers :: [Pair HeaderName *]) body
- Serv.Internal.Server.Type: data ServerValue
- Serv.Internal.Server.Type: deleteBody :: Response headers body -> Response headers Empty
- Serv.Internal.Server.Type: emptyResponse :: Status -> Response '[] Empty
- Serv.Internal.Server.Type: instance (Serv.Internal.Header.ReflectHeaders headers, Serv.Internal.MediaType.ReflectEncoders ctypes a) => Serv.Internal.Server.Type.WaiResponse headers ('Serv.Internal.Api.Body ctypes a)
- Serv.Internal.Server.Type: instance Serv.Internal.Header.ReflectHeaders headers => Serv.Internal.Server.Type.WaiResponse headers 'Serv.Internal.Api.Empty
- Serv.Internal.Server.Type: newtype Server m
- Serv.Internal.Server.Type: noOp :: Applicative m => m NotHere
- Serv.Internal.Server.Type: orElse :: Monad m => Server m -> Server m -> Server m
- Serv.Internal.Server.Type: resortHeaders :: RecordIso headers headers' => Response headers body -> Response headers' body
- Serv.Internal.Server.Type: routingError :: Monad m => RoutingError -> m ServerValue
- Serv.Internal.Server.Type: runServerWai :: Context -> (Response -> IO ResponseReceived) -> (Server IO -> IO ResponseReceived)
- Serv.Internal.Server.Type: transformServer :: (forall x. m x -> n x) -> Server m -> Server n
- Serv.Internal.Server.Type: waiResponse :: WaiResponse headers body => [Quality MediaType] -> Response headers body -> Response
- Serv.Internal.Server.Type: withBody :: a -> Response headers Empty -> Response headers (Body ctypes a)
- Serv.Internal.Server.Type: withHeader :: Proxy name -> value -> Response headers body -> Response ((name ::: value) : headers) body
- Serv.Internal.Server.Type: withQuietHeader :: HeaderEncode name value => Proxy name -> value -> Response headers body -> Response headers body
- Serv.Internal.URI: class URIDecode a
- Serv.Internal.URI: class URIEncode a
- Serv.Internal.URI: fromByteString :: URIDecode a => ByteString -> Either String a
- Serv.Internal.URI: instance Serv.Internal.URI.URIDecode Serv.Internal.RawText.RawText
- Serv.Internal.URI: uriDecode :: URIDecode a => Text -> Either String a
- Serv.Internal.URI: uriEncode :: URIEncode a => a -> Text
- Serv.Internal.Verb: DELETE :: Verb
- Serv.Internal.Verb: GET :: Verb
- Serv.Internal.Verb: HEAD :: Verb
- Serv.Internal.Verb: OPTIONS :: Verb
- Serv.Internal.Verb: PATCH :: Verb
- Serv.Internal.Verb: POST :: Verb
- Serv.Internal.Verb: PUT :: Verb
- Serv.Internal.Verb: class ReflectVerb (v :: Verb)
- Serv.Internal.Verb: data Verb
- Serv.Internal.Verb: instance GHC.Classes.Eq Serv.Internal.Verb.Verb
- Serv.Internal.Verb: instance GHC.Classes.Ord Serv.Internal.Verb.Verb
- Serv.Internal.Verb: instance GHC.Read.Read Serv.Internal.Verb.Verb
- Serv.Internal.Verb: instance GHC.Show.Show Serv.Internal.Verb.Verb
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.DELETE
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.GET
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.HEAD
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.OPTIONS
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.PATCH
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.POST
- Serv.Internal.Verb: instance Serv.Internal.Verb.ReflectVerb 'Serv.Internal.Verb.PUT
- Serv.Internal.Verb: reflectVerb :: ReflectVerb v => Proxy v -> Verb
- Serv.Internal.Verb: standardName :: Verb -> Method
- Serv.Server: (:<|>) :: a -> b -> (:<|>) a b
- Serv.Server: NotHere :: NotHere
- Serv.Server: class Handling (spec :: k) where type Impl spec (m :: * -> *) where {
- Serv.Server: data (:<|>) a b
- Serv.Server: data Config
- Serv.Server: data NotHere
- Serv.Server: data Response (headers :: [Pair HeaderName *]) body
- Serv.Server: data Server m
- Serv.Server: defaultConfig :: Config
- Serv.Server: emptyResponse :: Status -> Response '[] Empty
- Serv.Server: handle :: (Handling spec, Monad m) => Proxy spec -> Impl spec m -> Server m
- Serv.Server: makeApplication :: Config -> Server IO -> Application
- Serv.Server: noOp :: Applicative m => m NotHere
- Serv.Server: transformServer :: (forall x. m x -> n x) -> Server m -> Server n
- Serv.Server: type family Impl spec (m :: * -> *);
- Serv.Server: withBody :: a -> Response headers Empty -> Response headers (Body ctypes a)
- Serv.Server: withHeader :: Proxy name -> value -> Response headers body -> Response ((name ::: value) : headers) body
- Serv.Server: withQuietHeader :: HeaderEncode name value => Proxy name -> value -> Response headers body -> Response headers body
- Serv.Server: }
- Serv.URI: class URIDecode a
- Serv.URI: class URIEncode a
- Serv.URI: uriDecode :: URIDecode a => Text -> Either String a
- Serv.URI: uriEncode :: URIEncode a => a -> Text
+ Serv.Api: (:>) :: Path star -> Api star -> Api star
+ Serv.Api: Abstract :: Api star
+ Serv.Api: CaptureBody :: [star] -> star -> (Handler star) -> Handler star
+ Serv.Api: CaptureHeaders :: [(HeaderName, star)] -> (Handler star) -> Handler star
+ Serv.Api: CaptureQuery :: [(Symbol, star)] -> (Handler star) -> Handler star
+ Serv.Api: Const :: Symbol -> Path star
+ Serv.Api: Empty :: Body star
+ Serv.Api: Endpoint :: star -> [Handler star] -> Api star
+ Serv.Api: HasBody :: [star] -> star -> Body star
+ Serv.Api: Header :: HeaderName -> star -> Path star
+ Serv.Api: HeaderAs :: HeaderName -> Symbol -> Path star
+ Serv.Api: Method :: Verb -> [(Status, Output star)] -> Handler star
+ Serv.Api: OneOf :: [Api star] -> Api star
+ Serv.Api: Respond :: [(HeaderName, star)] -> (Body star) -> Output star
+ Serv.Api: Seg :: Symbol -> star -> Path star
+ Serv.Api: Wildcard :: Path star
+ Serv.Api: data Handler star
+ Serv.Api: data Output star
+ Serv.Api: instance (Data.Singletons.SingI n, Data.Singletons.SingI t) => Data.Singletons.SingI (Serv.Api.Header n t)
+ Serv.Api: instance (Data.Singletons.SingI n, Data.Singletons.SingI t) => Data.Singletons.SingI (Serv.Api.Seg n t)
+ Serv.Api: instance (Data.Singletons.SingI n, Data.Singletons.SingI v) => Data.Singletons.SingI (Serv.Api.HeaderAs n v)
+ Serv.Api: instance (Data.Singletons.SingI p, Data.Singletons.SingI k) => Data.Singletons.SingI (p Serv.Api.:> k)
+ Serv.Api: instance (Data.Singletons.SingI t, Data.Singletons.SingI ts) => Data.Singletons.SingI ('Serv.Api.Endpoint t ts)
+ Serv.Api: instance (Data.Singletons.SingI ts, Data.Singletons.SingI a) => Data.Singletons.SingI ('Serv.Api.HasBody ts a)
+ Serv.Api: instance (Data.Singletons.SingI ts, Data.Singletons.SingI a, Data.Singletons.SingI k) => Data.Singletons.SingI ('Serv.Api.CaptureBody ts a k)
+ Serv.Api: instance (Data.Singletons.SingI ts, Data.Singletons.SingI b) => Data.Singletons.SingI ('Serv.Api.Respond ts b)
+ Serv.Api: instance (Data.Singletons.SingI ts, Data.Singletons.SingI k) => Data.Singletons.SingI ('Serv.Api.CaptureHeaders ts k)
+ Serv.Api: instance (Data.Singletons.SingI ts, Data.Singletons.SingI k) => Data.Singletons.SingI ('Serv.Api.CaptureQuery ts k)
+ Serv.Api: instance (Data.Singletons.SingI v, Data.Singletons.SingI ts) => Data.Singletons.SingI ('Serv.Api.Method v ts)
+ Serv.Api: instance Data.Singletons.SingI 'Serv.Api.Empty
+ Serv.Api: instance Data.Singletons.SingI Serv.Api.Abstract
+ Serv.Api: instance Data.Singletons.SingI Serv.Api.Wildcard
+ Serv.Api: instance Data.Singletons.SingI s => Data.Singletons.SingI (Serv.Api.Const s)
+ Serv.Api: instance Data.Singletons.SingI ts => Data.Singletons.SingI ('Serv.Api.OneOf ts)
+ Serv.Api: type (:>) a b = a :> b
+ Serv.Api: type Abstract = Abstract
+ Serv.Api: type CaptureBody cTypes ty method = CaptureBody cTypes ty method
+ Serv.Api: type CaptureHeaders hdrs method = CaptureHeaders hdrs method
+ Serv.Api: type CaptureQuery query method = CaptureQuery query method
+ Serv.Api: type Const sym = Const sym
+ Serv.Api: type Empty = Empty
+ Serv.Api: type Endpoint ann ms = Endpoint ann ms
+ Serv.Api: type HasBody ctypes ty = HasBody ctypes ty
+ Serv.Api: type Header name ty = Header name ty
+ Serv.Api: type HeaderAs ty sym = HeaderAs ty sym
+ Serv.Api: type Method verb responses = Method verb responses
+ Serv.Api: type OneOf apis = OneOf apis
+ Serv.Api: type Respond hdrs body = Respond hdrs body
+ Serv.Api: type Seg sym ty = Seg sym ty
+ Serv.Api: type Wildcard = Wildcard
+ Serv.Api.Analysis: EndpointAnalysis :: Set Verb -> Set SomeHeaderName -> Set SomeHeaderName -> EndpointAnalysis
+ Serv.Api.Analysis: [headersEmitted] :: EndpointAnalysis -> Set SomeHeaderName
+ Serv.Api.Analysis: [headersExpected] :: EndpointAnalysis -> Set SomeHeaderName
+ Serv.Api.Analysis: [verbsHandled] :: EndpointAnalysis -> Set Verb
+ Serv.Api.Analysis: data EndpointAnalysis
+ Serv.Api.Analysis: headerNames :: Sing hts -> Set SomeHeaderName
+ Serv.Api.Analysis: headersExpectedOf :: Sing hs -> Set SomeHeaderName
+ Serv.Api.Analysis: inspectEndpoint :: Sing hs -> EndpointAnalysis
+ Serv.Api.Analysis: inspectHandler :: Sing h -> EndpointAnalysis
+ Serv.Api.Analysis: inspectVerbs :: Sing hs -> Set Verb
+ Serv.Api.Analysis: instance GHC.Base.Monoid Serv.Api.Analysis.EndpointAnalysis
+ Serv.Api.Prelude: class SingI (a :: k)
+ Serv.Api.Prelude: sing :: SingI a => Sing k a

Files

− app/TestServer.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE PartialTypeSignatures #-}-{-# LANGUAGE TypeOperators         #-}--import           Data.Function            ((&))-import           Data.Proxy-import           Data.Text                (Text)-import           Network.Wai.Handler.Warp (run)-import qualified Serv.Api                 as A-import           Serv.Common-import qualified Serv.ContentType         as Ct-import qualified Serv.Cors                as Cors-import qualified Serv.Header              as H-import qualified Serv.Header.Proxies      as Hp-import           Serv.Server--type RawBody = 'A.Body '[ Ct.TextPlain ] Text--type Api-  = 'A.Cors Cors.PermitAll 'A.:>-    'A.Endpoint-      '[ 'A.Method 'A.GET '[ 'H.CacheControl 'A.::: RawText ] RawBody ]--apiProxy :: Proxy Api-apiProxy = Proxy--impl :: Impl Api IO-impl = get :<|> noOp-  where-    get =-      return-      $ emptyResponse ok200-      & withHeader Hp.cacheControl "foo"-      & withBody "Hello"--server :: Server IO-server = handle apiProxy impl--main :: IO ()-main =-  run 8000 (makeApplication defaultConfig server)
serv.cabal view
@@ -1,7 +1,18 @@ name:                serv-version:             0.1.0.0-synopsis:            Dependently typed API server framework-description:         Please see README.md+version:             0.2.0.0+synopsis:            Dependently typed API framework+description:+  Types and kinds for describing APIs.+  .+  This package defines the kind 'Serv.Api.Api' which classifies types which+  statically describe an API. Define your 'Serv.Api.Api'-kinded types and then+  write/derive compliant servers, clients, and documentation all statically+  guaranteed to match.+  .+  Import "Serv.Api.Prelude" for the smoothest experience defining these types.+  .+  See the README for more details.+ homepage:            http://github.com/tel/serv#readme license:             BSD3 license-file:        LICENSE@@ -17,81 +28,18 @@   exposed-modules:      Serv.Api-    Serv.Common-    Serv.ContentType-    Serv.Cors-    Serv.Header-    Serv.Header.Proxies-    Serv.URI-    Serv.Internal.Api-    Serv.Internal.Api.Analysis-    Serv.Internal.Cors-    Serv.Internal.Header-    Serv.Internal.Header.Name-    Serv.Internal.Header.Serialization-    Serv.Internal.MediaType-    Serv.Internal.Pair-    Serv.Internal.Query-    Serv.Internal.RawText-    Serv.Internal.Rec-    Serv.Internal.Server-    Serv.Internal.Server.Config-    Serv.Internal.Server.Context-    Serv.Internal.Server.Error-    Serv.Internal.Server.Type-    Serv.Internal.URI-    Serv.Internal.Verb-    Serv.Server+    Serv.Api.Analysis+    Serv.Api.Prelude    build-depends:       base >= 4.7 && < 5-                     , aeson-                     , bytestring-                     , case-insensitive+                      , containers-                     , http-media-                     , http-types-                     , mtl-                     , tagged+                     , http-kinder+                     , singletons                      , text-                     , time-                     , transformers-                     , wai-  default-language:    Haskell2010 -executable test-server-  hs-source-dirs:      app-  main-is:             TestServer.hs-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N-  build-depends:       base-                     , serv-                     , wai-                     , warp-                     , text   default-language:    Haskell2010 -test-suite serv-test-  type:                exitcode-stdio-1.0-  hs-source-dirs:      test-  main-is:             Spec.hs-  other-modules:-    Examples.Ex1-    Examples.Ex2-  build-depends:       base-                     , serv--                     , HUnit-                     , QuickCheck-                     , tasty-                     , tasty-ant-xml-                     , tasty-hunit-                     , tasty-quickcheck-                     , text-                     , wai-                     , wai-extra--  ghc-options:         -threaded -rtsopts -with-rtsopts=-N-  default-language:    Haskell2010- source-repository head   type:     git-  location: https://github.com/githubuser/serv+  location: https://github.com/tel/serv
src/Serv/Api.hs view
@@ -1,15 +1,237 @@+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE PolyKinds            #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-}+{-# LANGUAGE UndecidableInstances #-} +-- | Types, but really kinds, which represent the structure of an API. module Serv.Api ( +  -- * API types/kinds+     Api (..)-  , Method (..)-  , Body (..)   , Path (..)-  , Verb (..)-  , Pair (..)+  , Handler (..)+  , Output (..)+  , Body (..) -  ) where+  -- ** Syntax sugar+  , type (:::) -import Serv.Internal.Api-import Serv.Internal.Verb-import Serv.Internal.Pair+  -- * Singletons+  , Sing (+        SEndpoint, SOneOf, SAbstract, (:%>)+      , SConst, SHeaderAs, SSeg, SHeader, SWildcard+      , SMethod, SCaptureBody, SCaptureHeaders, SCaptureQuery+      , SRespond+      , SHasBody, SEmpty+    )++  -- * Type aliases++  -- | Eliminates need for single-quoting the @DataKind@-lifted types.++  -- ** 'Api'+  , Endpoint, OneOf, Abstract, (:>)++  -- ** 'Path'+  , Const, HeaderAs, Seg, Header, Wildcard++  -- ** 'Handler'+  , Method, CaptureBody, CaptureHeaders, CaptureQuery++  -- ** 'Output'+  , Respond++  -- ** 'Body'+  , HasBody, Empty++) where++import           Data.Singletons+import           Data.Singletons.TypeLits+import           Network.HTTP.Kinder.Header (HeaderName)+import           Network.HTTP.Kinder.Status (Status)+import           Network.HTTP.Kinder.Verb++-- | Extra syntax-sugar for representing type-level pairs.+type a ::: b = '( a, b )+infixr 6 :::++-- | 'Handler' responses may opt to include a response body or not.+data Body star+  = HasBody [star] star+  -- ^ Return a response body by specifying a set of content-types and+  -- a value to derive the body from.+  | Empty+  -- ^ A response with an empty body++data instance Sing (b :: Body *)+  = forall ts a . b ~ HasBody ts a => SHasBody (Sing ts) (Sing a)+  | b ~ Empty => SEmpty++instance (SingI ts, SingI a) => SingI ('HasBody ts a :: Body *) where+  sing = SHasBody sing sing++instance SingI ('Empty :: Body *) where+  sing = SEmpty++type HasBody ctypes ty = 'HasBody ctypes ty+type Empty = 'Empty++++-- | Describes an output from an API under a given status.+data Output star = Respond [ (HeaderName, star) ] (Body star)++data instance Sing (o :: Output *)+  = forall ts b . o ~ Respond ts b => SRespond (Sing ts) (Sing b)++instance (SingI ts, SingI b) => SingI ('Respond ts b :: Output *) where+  sing = SRespond sing sing++type Respond hdrs body = 'Respond hdrs body+++++-- | A 'Handler' is a single HTTP verb response handled at a given 'Endpoint'.+-- In order to complete a 'Handler''s operation it may demand data from the+-- request such as headers or the request body.+data Handler star+  = Method Verb [(Status, Output star)]+    -- ^ A "core" 'Handler' definition which describes the 'Verb' it+    -- responds to along with a set of response headers and a chance to+    -- attach a response 'Body'.+  | CaptureBody [star] star (Handler star)+    -- ^ Augment a 'Handler' to include requirements of a request body.+  | CaptureHeaders [(HeaderName, star)] (Handler star)+    -- ^ Augment a 'Handler' to include requirements of request header values.+  | CaptureQuery [(Symbol, star)] (Handler star)+    -- ^ Augment a 'Handler' to include requirements of the request query+    -- string++data instance Sing (h :: Handler *)+  = forall v ts . h ~ Method v ts => SMethod (Sing v) (Sing ts)+  | forall ts a k . h ~ CaptureBody ts a k => SCaptureBody (Sing ts) (Sing a) (Sing k)+  | forall ts k . h ~ CaptureHeaders ts k => SCaptureHeaders (Sing ts) (Sing k)+  | forall ts k . h ~ CaptureQuery ts k => SCaptureQuery (Sing ts) (Sing k)++instance (SingI v, SingI ts) => SingI ('Method v ts :: Handler *) where+  sing = SMethod sing sing++instance (SingI ts, SingI a, SingI k) => SingI ('CaptureBody ts a k :: Handler *) where+  sing = SCaptureBody sing sing sing++instance (SingI ts, SingI k) => SingI ('CaptureHeaders ts k :: Handler *) where+  sing = SCaptureHeaders sing sing++instance (SingI ts, SingI k) => SingI ('CaptureQuery ts k :: Handler *) where+  sing = SCaptureQuery sing sing++type Method verb responses = 'Method verb responses+type CaptureBody cTypes ty method = 'CaptureBody cTypes ty method+type CaptureHeaders hdrs method = 'CaptureHeaders hdrs method+type CaptureQuery query method = 'CaptureQuery query method+++++-- | "Generalized" path segments match against data in the request.+data Path star+  = Const Symbol+    -- ^ Matches if the request has a non-empty remaining path and the next+    -- segment matches exactly+  | HeaderAs HeaderName Symbol+    -- ^ Matches if the request has a given header and its value matches+    -- exactly (!)+  | Seg Symbol star+    -- ^ Matches if the request has a non-empty remaining path. The next+    -- segment is "captured", provided to the server implementation.+  | Header HeaderName star+    -- ^ Always matches, "capturing" the value of a header, or 'Nothing' if+    -- the header fails to exist.+  | Wildcard+    -- ^ Always matches, "captures" the remaining path segments as a list+    -- of text values. May just capture the empty list.++data instance Sing (p :: Path *)+  = forall s . p ~ Const s => SConst (Sing s)+  | forall n v . p ~ HeaderAs n v => SHeaderAs (Sing n) (Sing v)+  | forall n t . p ~ Seg n t => SSeg (Sing n) (Sing t)+  | forall n t . p ~ Header n t => SHeader (Sing n) (Sing t)+  | p ~ Wildcard => SWildcard++instance SingI s => SingI (Const s :: Path *) where+  sing = SConst sing++instance (SingI n, SingI v) => SingI (HeaderAs n v :: Path *) where+  sing = SHeaderAs sing sing++instance (SingI n, SingI t) => SingI (Seg n t :: Path *) where+  sing = SSeg sing sing++instance (SingI n, SingI t) => SingI (Header n t :: Path *) where+  sing = SHeader sing sing++instance SingI (Wildcard :: Path *) where+  sing = SWildcard++type Const sym = 'Const sym+type HeaderAs ty sym = 'HeaderAs ty sym+type Seg sym ty = 'Seg sym ty+type Header name ty = 'Header name ty+type Wildcard = 'Wildcard+++++-- | 'Api's describe collections of HTTP endpoints accessible at+-- various segmented 'Path's.+data Api star+  = Endpoint star [Handler star]+    -- ^ An 'Endpoint' describes a root API which responds only to requests+    -- with empty paths. It matches on HTTP 'Method's which demand 'Verb's,+    -- 'HeaderName's, and 'Body's.+    --+    -- 'Endpoint' differs from 'OneOf' in that it can only choose between+    -- possible methods and automatically provides an 'OPTIONS' response.+  | OneOf [Api star]+    -- ^ 'Api's consist of many sub-'Api's which are attempted sequentially.+    -- @'OneOf' choices@ expresses this sequential search along a set of+    -- sub-'Api' @choices@.+  | Abstract+    -- ^ 'Abstract' enables the use of standard 'Wai.Application's within an+    -- 'Api'. These cannot be examined further through type analysis, but+    -- they are a common use case.+  | Path star :> Api star+    -- ^ Qualify an API using a series of 'Path' "segments"+infixr 5 :>++data instance Sing (a :: Api *)+  = forall t ts . a ~ Endpoint t ts => SEndpoint (Sing t) (Sing ts)+  | forall ts . a ~ OneOf ts => SOneOf (Sing ts)+  | a ~ Abstract => SAbstract+  | forall p k . a ~ (p :> k) => Sing p :%> Sing k++instance (SingI t, SingI ts) => SingI ('Endpoint t ts :: Api *) where+  sing = SEndpoint sing sing++instance SingI ts => SingI ('OneOf ts :: Api *) where+  sing = SOneOf sing++instance SingI (Abstract :: Api *) where+  sing = SAbstract++instance (SingI p, SingI k) => SingI (p :> k :: Api *) where+  sing = sing :%> sing++type Endpoint ann ms = 'Endpoint ann ms+type OneOf apis = 'OneOf apis+type Abstract = 'Abstract+type a :> b = a ':> b+
+ src/Serv/Api/Analysis.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE PolyKinds           #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators       #-}++-- | Typeclasses constructing functions which reflect and analyze API+-- types.+--+-- (/A little rough right now, sorry/)+module Serv.Api.Analysis where++import           Data.Monoid+import           Data.Set                      (Set)+import qualified Data.Set                      as Set+import           Data.Singletons+import           Data.Singletons.Prelude.List+import           Data.Singletons.Prelude.Tuple+import           Network.HTTP.Kinder.Header    (HeaderName, SomeHeaderName (..))+import           Network.HTTP.Kinder.Verb      (Verb)+import           Serv.Api++data EndpointAnalysis+  = EndpointAnalysis+    { verbsHandled :: Set Verb+    , headersExpected :: Set SomeHeaderName+    , headersEmitted :: Set SomeHeaderName+    }++instance Monoid EndpointAnalysis where+  mempty = EndpointAnalysis mempty mempty mempty+  mappend ea eb =+    EndpointAnalysis+    { verbsHandled = verbsHandled ea <> verbsHandled eb+    , headersExpected = headersExpected ea <> headersExpected eb+    , headersEmitted = headersEmitted ea <> headersEmitted eb+    }++inspectEndpoint :: forall (hs :: [Handler *]) . Sing hs -> EndpointAnalysis+inspectEndpoint s =+  case s of+    SNil -> mempty+    SCons sHandler sRest -> inspectHandler sHandler <> inspectEndpoint sRest++inspectHandler :: forall (h :: Handler *) . Sing h -> EndpointAnalysis+inspectHandler s =+  case s of+    SCaptureQuery _ sNext -> inspectHandler sNext+    SCaptureBody _ _ sNext -> inspectHandler sNext+    SMethod sVerb sResponses ->+      case sResponses of+        SNil -> mempty+        SCons (STuple2 _sCode (SRespond sHdrs _sBody)) sRest ->+          EndpointAnalysis+          { verbsHandled = Set.singleton (fromSing sVerb)+          , headersEmitted = headerNames sHdrs+          , headersExpected = Set.empty+          } <> inspectHandler (SMethod sVerb sRest)+    SCaptureHeaders sHdrs sNext ->+      EndpointAnalysis+      { verbsHandled = Set.empty+      , headersEmitted = Set.empty+      , headersExpected = headerNames sHdrs+      }+      <> inspectHandler sNext++headerNames :: forall (hts :: [(HeaderName, k)]) . Sing hts -> Set SomeHeaderName+headerNames s =+  case s of+    SNil -> Set.empty+    SCons (STuple2 sHt _sTy) sRest ->+      Set.insert (SomeHeaderName sHt) (headerNames sRest)++inspectVerbs :: forall (hs :: [Handler *]) . Sing hs -> Set Verb+inspectVerbs = verbsHandled . inspectEndpoint++headersExpectedOf :: forall (hs :: [Handler *]) . Sing hs -> Set SomeHeaderName+headersExpectedOf = headersExpected . inspectEndpoint
+ src/Serv/Api/Prelude.hs view
@@ -0,0 +1,19 @@++-- | Module containing everything you need to define an 'Api' type. Import+-- this unqualified for easy 'Api' definitions.+--+-- Exports the instance of 'SingI' for all 'Typeable' types. This will+-- cause issues for @CustomStar@-style 'SingI' instances, but is nearly+-- required for Serv.+module Serv.Api.Prelude (++    module Serv.Api+  , module Network.HTTP.Kinder+  , SingI (..)++) where++import           Data.Singletons+import           Data.Singletons.TypeRepStar ()+import           Network.HTTP.Kinder+import           Serv.Api
− src/Serv/Common.hs
@@ -1,4 +0,0 @@--module Serv.Common ( RawText (..) ) where--import Serv.Internal.RawText
− src/Serv/ContentType.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}--module Serv.ContentType (--    HasMediaType (..)-  , MimeEncode (..)-  , MimeDecode (..)-  , (//)-  , (/:)--    -- Standard Content Types-  , TextPlain-  , JSON--  ) where--import qualified Data.Aeson              as A-import qualified Data.ByteString.Lazy    as Sl-import           Data.Text               (Text)-import qualified Data.Text.Encoding      as Text-import           Network.HTTP.Media-import           Serv.Internal.MediaType--data TextPlain--instance HasMediaType TextPlain where-  mediaType _ = "text" // "plain"--instance MimeEncode TextPlain Text where-  mimeEncode _ = Text.encodeUtf8--data JSON--instance HasMediaType JSON where-  mediaType _ = "application" // "json"--instance A.ToJSON a => MimeEncode JSON a where-  mimeEncode _ = Sl.toStrict . A.encode--instance A.FromJSON a => MimeDecode JSON a where-  mimeDecode _ bs = A.eitherDecodeStrict bs
− src/Serv/Cors.hs
@@ -1,17 +0,0 @@--module Serv.Cors (--    Policy-  , Context (..)-  , AccessSet (..)--  , CorsPolicy (..)-  , PermitAll--  , permitAll-  , wildcard-  , predicateWhitelist--  ) where--import Serv.Internal.Cors
− src/Serv/Header.hs
@@ -1,12 +0,0 @@--module Serv.Header (--    HeaderName (..)-  , HeaderEncode (..)-  , HeaderDecode (..)-  , ReflectName--  ) where--import Serv.Internal.Header.Name-import Serv.Internal.Header.Serialization
− src/Serv/Header/Proxies.hs
@@ -1,75 +0,0 @@--module Serv.Header.Proxies (--    Proxy (..)-  , cacheControl-  , connection-  , contentLength-  , contentType-  , date-  , pragma-  , upgrade-  , via-  , warning-  , accept-  , acceptCharset-  , acceptEncoding-  , acceptLanguage-  , accessControlRequestMethod-  , accessControlRequestHeaders-  , authorization-  , cookie-  , expect-  , from-  , host-  , ifMatch-  , ifModifiedSince-  , ifNoneMatch-  , ifRange-  , ifUnmodifiedSince-  , maxForwards-  , origin-  , proxyAuthorization-  , range-  , referer-  , tE-  , userAgent-  , xForwardedFor-  , xForwardedHost-  , xForwardedProto-  , xCsrfToken-  , accessControlAllowOrigin-  , accessControlExposeHeaders-  , accessControlMaxAge-  , accessControlAllowCredentials-  , accessControlAllowMethods-  , accessControlAllowHeaders-  , acceptPatch-  , acceptRanges-  , age-  , allow-  , contentDisposition-  , contentEncoding-  , contentLanguage-  , contentLocation-  , contentRange-  , contentSecurityPolicy-  , eTag-  , expires-  , lastModified-  , link-  , location-  , proxyAuthenticate-  , publicKeyPins-  , retryAfter-  , setCookie-  , strictTransportSecurity-  , trailer-  , transferEncoding-  , vary-  , wWWAuthenticate--  ) where--import           Data.Proxy-import           Serv.Internal.Header.Name
− src/Serv/Internal/Api.hs
@@ -1,106 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}---- | Types, but really kinds, which represent the structure of an API.-module Serv.Internal.Api where--import           GHC.TypeLits-import           Serv.Internal.Header (HeaderName)-import           Serv.Internal.Pair-import           Serv.Internal.Verb----- | 'Api's describe collections of HTTP endpoints accessible at--- various segmented 'Path's.------ An 'Endpoint' describes a root API which responds--- only to requests with empty paths. It matches on HTTP 'Method's--- which demand 'Verb's, 'HeaderName's, and 'Body's.------ 'Endpoint' differs from 'OneOf' in that it can only choose between--- possible methods and automatically provides an 'OPTIONS' response.------ 'Api's consist of many sub-'Api's which are attempted sequentially.--- @'OneOf' choices@ expresses this sequential search along a set of sub-'Api'--- @choices@.------ 'Raw' enables the use of standard 'Wai.Application's within an 'Api'.--- These cannot be examined further through type analysis, but they are a--- common use case.------ Qualify an API using a series of 'Path' qualifiers.-data Api star where-  Endpoint :: [Method star] -> Api star-  OneOf :: [Api star] -> Api star-  Raw :: Api star-  (:>) :: Path star -> Api star -> Api star--infixr 5 :>---- | A 'Method' is a single HTTP verb response handled at a given 'Endpoint'.--- In order to complete a 'Method''s operation it may demand data from the--- request such as headers or the request body.------ A "core" 'Method' definition which describes the 'Verb' it responds--- to along with a set of response headers and a chance to attach a--- response 'Body'.------ Augment a 'Method' to include requirements of a request body.------ Augment a 'Method' to include requirements of request header values.----data Method star where-  Method :: Verb -> [Pair HeaderName star] -> Body star -> Method star-  CaptureBody :: [star] -> star -> Method star -> Method star-  CaptureHeaders :: [Pair HeaderName star] -> Method star -> Method star-  CaptureQuery :: [Pair Symbol star] -> Method star -> Method star---- | 'Method' responses may opt to include a response body or not.------ Return a response body by specifying a set of content-types--- and a value to derive the body from.------ A response with an empty body-data Body star where-  Body :: [star] -> star -> Body star-  Empty :: Body star---- | "Generalized" path segments match against data in the request.------ Matches if the request has a non-empty remaining path and--- the next segment matches exactly------ Matches if the request has a given header and its value--- matches exactly (!)------ Matches if the request has a non-empty remaining path.--- The next segment is "captured", provided to the server implementation.------ Always matches, "capturing" the value of a header, or 'Nothing' if--- the header fails to exist.------ Always matches, "captures" the remaining path segments as a list--- of text values. May just capture the empty list.------ Always matches, "captures" the existence of a query flag by--- returning 'True' if the flag is provided and 'False' otherwise.------ Always matches, "capturing" the value of a query parameter.-data Path star where-  Const :: Symbol -> Path star-  HeaderAs :: HeaderName -> Symbol -> Path star-  Seg :: Symbol -> star -> Path star-  Header :: HeaderName -> star -> Path star-  Wildcard :: Path star-  Flag :: Symbol -> Path star-  QueryParam :: Symbol -> star -> Path star-  Cors :: star -> Path star
− src/Serv/Internal/Api/Analysis.hs
@@ -1,110 +0,0 @@-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE KindSignatures      #-}-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}---- | Typeclasses constructing functions which reflect and analyze API--- types.-module Serv.Internal.Api.Analysis where--import           Data.Function        ((&))-import           Data.Monoid-import           Data.Proxy-import           Data.Set             (Set)-import qualified Data.Set             as Set-import qualified Network.HTTP.Types   as HTTP-import           Serv.Internal.Api-import qualified Serv.Internal.Header as Header-import qualified Serv.Internal.Verb   as Verb--class VerbsOf methods where-  verbsOf :: Proxy methods -> Set Verb.Verb--instance VerbsOf '[] where-  verbsOf Proxy = Set.singleton Verb.OPTIONS--instance-  (Verb.ReflectVerb verb, VerbsOf methods) =>-    VerbsOf ('Method verb headers body ': methods)-  where-    verbsOf Proxy =-      case Verb.reflectVerb (Proxy :: Proxy verb) of-        Verb.GET ->-          verbsOf (Proxy :: Proxy methods)-          & Set.insert Verb.GET-          & Set.insert Verb.HEAD-        verb -> Set.insert verb (verbsOf (Proxy :: Proxy methods))--class HeadersExpectedOf (methods :: [Method *]) where-  headersExpectedOf :: Proxy methods -> Set HTTP.HeaderName--instance HeadersExpectedOf '[] where-  headersExpectedOf _ = Set.empty--instance-  HeadersExpectedOf rs => HeadersExpectedOf ('Method verb headers body ': rs)-  where-    -- No headers are expected from a bottom method-    headersExpectedOf _ = headersExpectedOf (Proxy :: Proxy rs)--instance-  (HeadersExpectedOf (method ': rs), Header.ReflectHeaderNames hdrs) =>-  HeadersExpectedOf ('CaptureHeaders hdrs method ': rs)-  where-    headersExpectedOf _ =-      Set.fromList (Header.reflectHeaderNames (Proxy :: Proxy hdrs))-      <>-      headersExpectedOf (Proxy :: Proxy (method ': rs))--instance-  HeadersExpectedOf (method ': rs) =>-  HeadersExpectedOf ('CaptureBody ctypes ty method ': rs)-  where-    headersExpectedOf _ =-      headersExpectedOf (Proxy :: Proxy (method ': rs))--instance-  HeadersExpectedOf (method ': rs) =>-  HeadersExpectedOf ('CaptureQuery names method ': rs)-  where-    headersExpectedOf _ =-      headersExpectedOf (Proxy :: Proxy (method ': rs))--class HeadersReturnedBy (methods :: [Method *]) where-  headersReturnedBy :: Proxy methods -> Set HTTP.HeaderName--instance HeadersReturnedBy '[] where-  headersReturnedBy _ = Set.empty--instance-  (Header.ReflectHeaderNames headers, HeadersReturnedBy rs) =>-  HeadersReturnedBy ('Method verb headers body ': rs)-  where-    headersReturnedBy _ =-      Set.fromList (Header.reflectHeaderNames (Proxy :: Proxy headers))-      <>-      headersReturnedBy (Proxy :: Proxy rs)--instance-  HeadersReturnedBy (method ': rs) =>-  HeadersReturnedBy ('CaptureHeaders hdrs method ': rs)-  where-    headersReturnedBy _ =-      headersReturnedBy (Proxy :: Proxy (method ': rs))--instance-  HeadersReturnedBy (method ': rs) =>-  HeadersReturnedBy ('CaptureBody ctypes ty method ': rs)-  where-    headersReturnedBy _ =-      headersReturnedBy (Proxy :: Proxy (method ': rs))--instance-  HeadersReturnedBy (method ': rs) =>-  HeadersReturnedBy ('CaptureQuery names method ': rs)-  where-    headersReturnedBy _ =-      headersReturnedBy (Proxy :: Proxy (method ': rs))
− src/Serv/Internal/Cors.hs
@@ -1,127 +0,0 @@--module Serv.Internal.Cors where--import           Control.Applicative-import           Control.Monad-import           Data.Maybe                         (catMaybes)-import           Data.Monoid-import           Data.Proxy-import           Data.Set                           (Set)-import           Data.Text                          (Text)-import           Data.Time-import qualified Network.HTTP.Types                 as HTTP-import qualified Serv.Header.Proxies                as Hp-import qualified Serv.Internal.Header.Serialization as Hs-import           Serv.Internal.Server.Config-import           Serv.Internal.Verb                 (Verb)---- | A 'CorsPolicy' interprets the request's provided Origin and the--- current routing context to determine how to expose resources to the--- requestor.-type Policy = Config -> Context -> AccessSet---- | Class describing types which describe CORS 'Policy's.-class CorsPolicy m where-  corsPolicy :: Proxy m -> Policy---- | The 'PermitAll' policy produces the `permitAll` `Policy`.-data PermitAll--instance CorsPolicy PermitAll where-  corsPolicy _ = permitAll--headerSet :: Bool -> Context -> AccessSet -> [HTTP.Header]-headerSet includeMethods ctx access-  | not (originAllowed access) = []-  | otherwise =-      catMaybes-      [ Hs.headerPair Hp.accessControlMaxAge (maxAge access)-      , do guard includeMethods-           Hs.headerPair Hp.accessControlAllowMethods (methodsAllowed access)-      , Hs.headerPair Hp.accessControlAllowOrigin (origin ctx)-      , Hs.headerPair Hp.accessControlExposeHeaders (headersExposed access)-      , Hs.headerPair Hp.accessControlAllowHeaders (headersAllowed access)-      , Hs.headerPair Hp.accessControlAllowCredentials (credentialsAllowed access)-      ]---- | The 'CorsContext' provides data from which we can make choices about--- how to respond to CORS requests.-data Context-  = Context-   { origin           :: Text-   , headersExpected  :: Set HTTP.HeaderName-   , headersReturned  :: Set HTTP.HeaderName-   , methodsAvailable :: Set Verb-   }--mergeContext :: Context -> Context -> Context-mergeContext a b =-  Context-  { origin = origin a-  , headersExpected = headersExpected a <> headersExpected b-  , headersReturned = headersReturned a <> headersReturned b-  , methodsAvailable = methodsAvailable a <> methodsAvailable b-  }---- | Descrbes what parts of the response should be made available--- cross-origin. The Monoid product on 'AccessSet's permits all accesses of--- either of the constituents.-data AccessSet =-  AccessSet-  { originAllowed      :: Bool-  , headersExposed     :: Set HTTP.HeaderName-  , credentialsAllowed :: Bool-  , methodsAllowed     :: Set Verb-  , headersAllowed     :: Set HTTP.HeaderName-  , maxAge             :: Maybe NominalDiffTime-  }---- | The empty access set disallows all CORS access while the product @l <>--- r@ provides access to a particular part of the response if either @l@ or--- @r@ does.-instance Monoid AccessSet where-  mempty =-    AccessSet-    { originAllowed = False-    , headersExposed = mempty-    , credentialsAllowed = False-    , methodsAllowed = mempty-    , headersAllowed = mempty-    , maxAge = Nothing-    }-  mappend a b =-    AccessSet-    { originAllowed = originAllowed a || originAllowed b-    , headersExposed = headersExposed a <> headersExposed b-    , credentialsAllowed = credentialsAllowed a || credentialsAllowed b-    , methodsAllowed = methodsAllowed a <> methodsAllowed b-    , headersAllowed = headersAllowed a <> headersAllowed b-    , maxAge = liftA2 max (maxAge a) (maxAge b)-    }----- | The most permissive CORS 'Policy' possible. Differs from Wildcard in--- that it allows credentials. Max age is not provided (so no caching)-permitAll :: Policy-permitAll _config ctx =-  AccessSet-  { originAllowed  = True-  , headersExposed = headersReturned ctx-  , headersAllowed = headersExpected ctx-  , credentialsAllowed = True-  , methodsAllowed = methodsAvailable ctx-  , maxAge = Nothing-  }---- | Effects a wildcard policy which provides maximal cross-origin access--- to all request origins. This disallows credentials use, however.-wildcard :: Policy-wildcard config ctx =-  (permitAll config ctx)-  { credentialsAllowed = False }---- | Provides access to all origins which pass a predicate-predicateWhitelist :: (Text -> Bool) -> Policy-predicateWhitelist originOk config ctx =-  (permitAll config ctx)-  { originAllowed = originOk (origin ctx) }
− src/Serv/Internal/Header.hs
@@ -1,64 +0,0 @@-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeOperators       #-}--module Serv.Internal.Header (--  HeaderName (..),-  reflectName,-  ReflectName,-  ReflectHeaders (..),-  ReflectHeaderNames (..),-  HeaderEncode (..),-  headerEncodeRaw,-  headerPair,-  HeaderDecode (..),-  headerDecodeRaw--  ) where--import           Data.Proxy-import           Data.Text.Encoding                 (encodeUtf8)-import qualified Network.HTTP.Types                 as HTTP-import           Serv.Internal.Header.Name-import           Serv.Internal.Header.Serialization-import           Serv.Internal.Pair-import           Serv.Internal.Rec---- | Given a header set description, reflect out all of the names-class ReflectHeaderNames headers where-  reflectHeaderNames :: Proxy headers -> [HTTP.HeaderName]--instance ReflectHeaderNames '[] where-  reflectHeaderNames _ = []--instance-  (ReflectName name, ReflectHeaderNames hdrs) =>-  ReflectHeaderNames (name '::: ty ': hdrs)-  where-    reflectHeaderNames _ =-      reflectName (Proxy :: Proxy name)-      : reflectHeaderNames (Proxy :: Proxy hdrs)---- | Given a record of headers, encode them into a list of header pairs.-class ReflectHeaders headers where-  reflectHeaders :: Rec headers -> [HTTP.Header]--instance ReflectHeaders '[] where-  reflectHeaders Nil = []--instance-  (ReflectName name, HeaderEncode name ty, ReflectHeaders headers) =>-    ReflectHeaders ( name '::: ty ': headers )-  where-    reflectHeaders (Cons val headers) =-      -- NOTE: Utf8 encoding is somewhat significantly too lax-      case headerEncode proxy val of-        Nothing -> reflectHeaders headers-        Just txt -> (reflectName proxy, encodeUtf8 txt) : reflectHeaders headers-      where-        proxy = Proxy :: Proxy name
− src/Serv/Internal/Header/Name.hs
@@ -1,725 +0,0 @@-{-# LANGUAGE DataKinds           #-}-{-# LANGUAGE KindSignatures      #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE PolyKinds           #-}-{-# LANGUAGE ScopedTypeVariables #-}--module Serv.Internal.Header.Name where--import           Data.Proxy-import           Data.String-import           GHC.TypeLits-import qualified Network.HTTP.Types as HTTP---- This is a GHC 8 feature. It won't work today because we--- cannot promote a GADT the way that we'd like to. Otherwise,--- we'd let each name specify its "direction".------ For instance, we'd have------     data HeaderName (d :: Direction) where---       Name :: Symbol -> HeaderName d---       CacheControl :: HeaderName d---       Accept :: HeaderName Request---       Allow :: HeaderName Response------ etc.------     -- | Qualifier of header types.---     data Direction = Request | Response---- | The variant (name and meaning) of a HTTP header.------ An incomplete listing of most permanant headers, a selection of provisional--- ones, and one or two non-standard headers. Generally, any header desired can--- be specified using the 'Name' constructor.------ Used only as their @DataKinds@ types system.-data HeaderName--  ---- WILDCARD HEADER NAMES--  = HeaderName Symbol-    -- ^ Inject an arbitatry symbol in as a 'HeaderName'. This can be used to-    -- implement any sort of custom header----  ---- COMMON HEADER NAMES---  | CacheControl-    -- ^ Used to specify directives that must be obeyed by all caching mechanisms-    -- along the request-response chain. Tells all caching mechanisms from server-    -- to client whether they may cache this object. It is measured in seconds-    ---    --     Cache-Control: no-cache--  | Connection-    -- ^ Control options for the current connection and list of hop-by-hop-    -- request fields-    ---    --     Connection: keep-alive-    --     Connection: Upgrade--  | ContentLength-    -- ^ The length of the request body in octets (8-bit bytes)-    ---    --     Content-Length: 348--  | ContentType-    -- ^ The MIME type of the body of the request (used with POST and PUT requests)-    ---    --     Content-Type: application/x-www-form-urlencoded--  | Date-    -- ^ The date and time that the message was sent (in "HTTP-date" format as-    -- defined by RFC 7231 Date/Time Formats)-    ---    --     Date: Tue, 15 Nov 1994 08:12:31 GMT--  | Pragma-    -- ^ Implementation-specific fields that may have various effects anywhere-    -- along the request-response chain.-    ---    --     Pragma: no-cache--  | Upgrade-    -- ^ Ask the server to upgrade to another protocol.-    ---    --     Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11--  | Via-    -- ^ Informs the server of proxies through which the request was sent.-    ---    --     Via: 1.0 fred, 1.1 example.com (Apache/1.1)--  | Warning-    -- ^ A general warning about possible problems with the entity body.-    ---    --     Warning: 199 Miscellaneous warning----    ---- REQUEST-SPECIFIC HEADER NAMES---  | Accept-    -- ^ Content-Types that are acceptable for the response.-    ---    --     Accept: text/plain--  | AcceptCharset-    -- ^ Character sets that are acceptable-    ---    --     Accept-Charset: utf-8--  | AcceptEncoding-    -- ^ List of acceptable encodings.-    ---    --     Accept-Encoding: gzip, deflate--  | AcceptLanguage-    -- ^ List of acceptable human languages for response.-    ---    --     Accept-Language: en-US--  | AccessControlRequestMethod-    -- ^ Used when issuing a preflight request to let the server-    -- know what HTTP method will be used when the actual request is made.-    ---    --     Access-Control-Request-Method: POST--  | AccessControlRequestHeaders-    -- ^ Used when issuing a preflight request to let the server know-    -- what HTTP headers will be used when the actual request is made.-    ---    --     Access-Control-Request-Headers: X-PINGOTHER--  | Authorization-    -- ^ Authentication credentials for HTTP authentication-    ---    --     Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==--  | Cookie-    -- ^ An HTTP cookie previously sent by the server with Set-Cookie (below)-    ---    --     Cookie: $Version=1; Skin=new;--  | Expect-    -- ^ Indicates that particular server behaviors are required by the client-    ---    --     Expect: 100-continue--  | From-    -- ^ The email address of the user making the request-    ---    --     From: user@example.com--  | Host-    -- ^ The domain name of the server (for virtual hosting), and the TCP port-    -- number on which the server is listening. The port number may be omitted-    -- if the port is the standard port for the service requested.-    ---    --     Host: en.wikipedia.org:80-    --     Host: en.wikipedia.org--  | IfMatch-    -- ^ Only perform the action if the client supplied entity matches the same-    -- entity on the server. This is mainly for methods like PUT to only update-    -- a resource if it has not been modified since the user last updated it.-    ---    --     If-Match: "737060cd8c284d8af7ad3082f209582d"--  | IfModifiedSince-    -- ^ Allows a 304 Not Modified to be returned if content is unchanged-    ---    --     If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT--  | IfNoneMatch-    -- ^ Allows a 304 Not Modified to be returned if content is unchanged,-    -- see HTTP ETag-    ---    --     If-None-Match: "737060cd8c284d8af7ad3082f209582d"--  | IfRange-    -- ^ If the entity is unchanged, send me the part(s) that I am missing;-    -- otherwise, send me the entire new entity-    ---    --     If-Range: "737060cd8c284d8af7ad3082f209582d"--  | IfUnmodifiedSince-    -- ^ Only send the response if the entity has not been modified since a-    -- specific time.-    ---    --     If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT--  | MaxForwards-    -- ^ Limit the number of times the message can be forwarded through proxies-    -- or gateways.-    ---    --     Max-Forwards: 10--  | Origin-    -- ^ Initiates a request for cross-origin resource sharing (asks server for-    -- an 'Access-Control-Allow-Origin' response field).-    ---    -- Origin: http://www.example-social-network.com--  | ProxyAuthorization-    -- ^ Authorization credentials for connecting to a proxy.-    ---    --     Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==--  | Range-    -- ^ Request only part of an entity. Bytes are numbered from 0.-    ---    --     Range: bytes=500-999--  | Referer-    -- ^ This is the address of the previous web page from which a link to the-    -- currently requested page was followed. (The word “referrer” has been-    -- misspelled in the RFC as well as in most implementations to the point-    -- that it has become standard usage and is considered correct terminology)-    ---    --     Referer: http://en.wikipedia.org/wiki/Main_Page--  | TE-    -- ^ The transfer encodings the user agent is willing to accept: the same-    -- values as for the response header field Transfer-Encoding can be used,-    -- plus the "trailers" value (related to the "chunked" transfer method) to-    -- notify the server it expects to receive additional fields in the trailer-    -- after the last, zero-sized, chunk.-    ---    --     TE: trailers, deflate--  | UserAgent-    -- ^ The user agent string of the user agent-    ---    --     User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0--  | XForwardedFor-    -- ^ A de facto standard for identifying the originating IP address of a-    -- client connecting to a web server through an HTTP proxy or load balancer-    ---    --     X-Forwarded-For: client1, proxy1, proxy2-    --     X-Forwarded-For: 129.78.138.66, 129.78.64.103--  | XForwardedHost-    -- ^ A de facto standard for identifying the original host requested by the client in-    -- the Host HTTP request header, since the host name and/or port of the reverse-    -- proxy (load balancer) may differ from the origin server handling the request.-    ---    --     X-Forwarded-Host: en.wikipedia.org:80-    --     X-Forwarded-Host: en.wikipedia.org--  | XForwardedProto-    -- ^ A de facto standard for identifying the originating protocol of an HTTP request,-    -- since a reverse proxy (or a load balancer) may communicate with a web server using-    -- HTTP even if the request to the reverse proxy is HTTPS.--  | XCsrfToken-    -- ^ Used to prevent cross-site request forgery.-    ---    --     X-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql-----    ---- RESPONSE-SPECIFIC HEADER NAMES---  | AccessControlAllowOrigin-    -- ^ When responding to a CORS request this lists either-    -- an origin or @*@ describing the server's CORS policy for-    -- the requested resource-    ---    --     Access-Control-Allow-Origin: *-    --     Access-Control-Allow-Origin: http://foo.example-    --     Access-Control-Allow-Origin: https://foo.example--  | AccessControlExposeHeaders-    -- ^ This header lets a server whitelist headers that browsers are allowed to access.-    ---    --     Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header--  | AccessControlMaxAge-    -- ^ This header indicates how long the results of a preflight request can be cached.-    ---    --     Access-Control-Max-Age: <delta-seconds>--  | AccessControlAllowCredentials-    -- ^ Indicates whether or not the response to the request can be exposed when the-    -- credentials flag is true. When used as part of a response to a preflight request,-    -- this indicates whether or not the actual request can be made using credentials. Note-    -- that simple GET requests are not preflighted, and so if a request is made for a-    -- resource with credentials, if this header is not returned with the resource, the-    -- response is ignored by the browser and not returned to web content.-    ---    --     Access-Control-Allow-Credentials: true | false--  | AccessControlAllowMethods-    -- ^ Specifies the method or methods allowed when accessing the resource. This is-    -- used in response to a preflight request.-    ---    --     Access-Control-Allow-Methods: <method>[, <method>]*--  | AccessControlAllowHeaders-    -- ^ Used in response to a preflight request to indicate which HTTP headers can-    -- be used when making the actual request.--  | AcceptPatch-    -- ^ Specifies which patch document formats this server supports-    ---    --     Accept-Patch: text/example;charset=utf-8--  | AcceptRanges-    -- ^ What partial content range types this server supports via byte serving-    ---    --     Accept-Ranges: bytes--  | Age-    -- ^ The age the object has been in a proxy cache in seconds-    ---    --     Age: 12--  | Allow-    -- ^ Valid actions for a specified resource. To be used for a 405 Method not allowed-    ---    --     Allow: GET, HEAD--  | ContentDisposition-    -- ^ An opportunity to raise a "File Download" dialogue box for a known MIME type-    -- with binary format or suggest a filename for dynamic content. Quotes are-    -- necessary with special characters.-    ---    --     Content-Disposition: attachment; filename="fname.ext"--  | ContentEncoding-    -- ^ The type of encoding used on the data.-    ---    --     Content-Encoding: gzip--  | ContentLanguage-    -- ^ The natural language or languages of the intended audience for the enclosed content-    ---    --     Content-Language: da--  | ContentLocation-    -- ^ An alternate location for the returned data-    ---    --     Content-Location: /index.htm--  | ContentRange-    -- ^ Where in a full body message this partial message belongs-    ---    --     Content-Range: bytes 21010-47021/47022--  | ContentSecurityPolicy-    -- ^ Content Security Policy definition.-    ---    --     Content-Security-Policy: default-src 'self'--  | ETag-    -- ^ An identifier for a specific version of a resource, often a message digest-    ---    --     ETag: "737060cd8c284d8af7ad3082f209582d"--  | Expires-    -- ^ Gives the date/time after which the response is considered stale (in-    -- "HTTP-date" format as defined by RFC 7231)-    ---    --     Expires: Thu, 01 Dec 1994 16:00:00 GMT--  | LastModified-    -- ^ The last modified date for the requested object (in "HTTP-date" format as-    -- defined by RFC 7231)-    ---    --     Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT--  | Link-    -- ^ Used to express a typed relationship with another resource, where the-    -- relation type is defined by RFC 5988-    ---    --     Link: </feed>; rel="alternate"--  | Location-    -- ^ Used in redirection, or when a new resource has been created.-    ---    --     Location: http://www.w3.org/pub/WWW/People.html--  | ProxyAuthenticate-    -- ^ Request authentication to access the proxy.-    ---    --     Proxy-Authenticate: Basic--  | PublicKeyPins-    -- ^ HTTP Public Key Pinning, announces hash of website's authentic TLS certificate-    ---    --     Public-Key-Pins: max-age=2592000; pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";--  | RetryAfter-    -- ^ If an entity is temporarily unavailable, this instructs the client to-    -- try again later. Value could be a specified period of time (in seconds) or a HTTP-date.-    ---    --     Retry-After: 120-    --     Retry-After: Fri, 07 Nov 2014 23:59:59 GMT--  | SetCookie-    -- ^ An HTTP cookie-    ---    --     Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1--  | StrictTransportSecurity-    -- ^ A HSTS Policy informing the HTTP client how long to cache the HTTPS only-    -- policy and whether this applies to subdomains.-    ---    --     Strict-Transport-Security: max-age=16070400; includeSubDomains--  | Trailer-    -- ^ The Trailer general field value indicates that the given set of header fields-    -- is present in the trailer of a message encoded with chunked transfer coding.-    ---    --     Trailer: Max-Forwards--  | TransferEncoding-    -- ^ The form of encoding used to safely transfer the entity to the user. Currently defined-    -- methods are: chunked, compress, deflate, gzip, identity.-    ---    --     Transfer-Encoding: chunked--  | Vary-    -- ^ Tells downstream proxies how to match future request headers to decide whether-    -- the cached response can be used rather than requesting a fresh one from the origin server.-    ---    --     Vary: *-    --     Vary: Accept-Language--  | WWWAuthenticate-    -- ^ Indicates the authentication scheme that should be used to access the requested entity.-    ---    --     WWW-Authenticate: Basic---- | Implements reflection of 'Name' types into 'HTTP.HeaderName' values for runtime use.-class ReflectName (n :: HeaderName) where-  reflectName :: proxy n -> HTTP.HeaderName----- Proxies--- ------------------------------------------------------------------------------cacheControl :: Proxy 'CacheControl-cacheControl = Proxy--connection :: Proxy 'Connection-connection = Proxy--contentLength :: Proxy 'ContentLength-contentLength = Proxy--contentType :: Proxy 'ContentType-contentType = Proxy--date :: Proxy 'Date-date = Proxy--pragma :: Proxy 'Pragma-pragma = Proxy--upgrade :: Proxy 'Upgrade-upgrade = Proxy--via :: Proxy 'Via-via = Proxy--warning :: Proxy 'Warning-warning = Proxy--accept :: Proxy 'Accept-accept = Proxy--acceptCharset :: Proxy 'AcceptCharset-acceptCharset = Proxy--acceptEncoding :: Proxy 'AcceptEncoding-acceptEncoding = Proxy--acceptLanguage :: Proxy 'AcceptLanguage-acceptLanguage = Proxy--accessControlRequestMethod :: Proxy 'AccessControlRequestMethod-accessControlRequestMethod = Proxy--accessControlRequestHeaders :: Proxy 'AccessControlRequestHeaders-accessControlRequestHeaders = Proxy--authorization :: Proxy 'Authorization-authorization = Proxy--cookie :: Proxy 'Cookie-cookie = Proxy--expect :: Proxy 'Expect-expect = Proxy--from :: Proxy 'From-from = Proxy--host :: Proxy 'Host-host = Proxy--ifMatch :: Proxy 'IfMatch-ifMatch = Proxy--ifModifiedSince :: Proxy 'IfModifiedSince-ifModifiedSince = Proxy--ifNoneMatch :: Proxy 'IfNoneMatch-ifNoneMatch = Proxy--ifRange :: Proxy 'IfRange-ifRange = Proxy--ifUnmodifiedSince :: Proxy 'IfUnmodifiedSince-ifUnmodifiedSince = Proxy--maxForwards :: Proxy 'MaxForwards-maxForwards = Proxy--origin :: Proxy 'Origin-origin = Proxy--proxyAuthorization :: Proxy 'ProxyAuthorization-proxyAuthorization = Proxy--range :: Proxy 'Range-range = Proxy--referer :: Proxy 'Referer-referer = Proxy--tE :: Proxy 'TE-tE = Proxy--userAgent :: Proxy 'UserAgent-userAgent = Proxy--xForwardedFor :: Proxy 'XForwardedFor-xForwardedFor = Proxy--xForwardedHost :: Proxy 'XForwardedHost-xForwardedHost = Proxy--xForwardedProto :: Proxy 'XForwardedProto-xForwardedProto = Proxy--xCsrfToken :: Proxy 'XCsrfToken-xCsrfToken = Proxy--accessControlAllowOrigin :: Proxy 'AccessControlAllowOrigin-accessControlAllowOrigin = Proxy--accessControlExposeHeaders :: Proxy 'AccessControlExposeHeaders-accessControlExposeHeaders = Proxy--accessControlMaxAge :: Proxy 'AccessControlMaxAge-accessControlMaxAge = Proxy--accessControlAllowCredentials :: Proxy 'AccessControlAllowCredentials-accessControlAllowCredentials = Proxy--accessControlAllowMethods :: Proxy 'AccessControlAllowMethods-accessControlAllowMethods = Proxy--accessControlAllowHeaders :: Proxy 'AccessControlAllowHeaders-accessControlAllowHeaders = Proxy--acceptPatch :: Proxy 'AcceptPatch-acceptPatch = Proxy--acceptRanges :: Proxy 'AcceptRanges-acceptRanges = Proxy--age :: Proxy 'Age-age = Proxy--allow :: Proxy 'Allow-allow = Proxy--contentDisposition :: Proxy 'ContentDisposition-contentDisposition = Proxy--contentEncoding :: Proxy 'ContentEncoding-contentEncoding = Proxy--contentLanguage :: Proxy 'ContentLanguage-contentLanguage = Proxy--contentLocation :: Proxy 'ContentLocation-contentLocation = Proxy--contentRange :: Proxy 'ContentRange-contentRange = Proxy--contentSecurityPolicy :: Proxy 'ContentSecurityPolicy-contentSecurityPolicy = Proxy--eTag :: Proxy 'ETag-eTag = Proxy--expires :: Proxy 'Expires-expires = Proxy--lastModified :: Proxy 'LastModified-lastModified = Proxy--link :: Proxy 'Link-link = Proxy--location :: Proxy 'Location-location = Proxy--proxyAuthenticate :: Proxy 'ProxyAuthenticate-proxyAuthenticate = Proxy--publicKeyPins :: Proxy 'PublicKeyPins-publicKeyPins = Proxy--retryAfter :: Proxy 'RetryAfter-retryAfter = Proxy--setCookie :: Proxy 'SetCookie-setCookie = Proxy--strictTransportSecurity :: Proxy 'StrictTransportSecurity-strictTransportSecurity = Proxy--trailer :: Proxy 'Trailer-trailer = Proxy--transferEncoding :: Proxy 'TransferEncoding-transferEncoding = Proxy--vary :: Proxy 'Vary-vary = Proxy--wWWAuthenticate :: Proxy 'WWWAuthenticate-wWWAuthenticate = Proxy----- ReflectName Instances------ A very verbose way of matching on lots of simple types. Not really worth--- your time reading. Heavy potential for bugs.--- -------------------------------------------------------------------------------instance KnownSymbol s => ReflectName ('HeaderName s) where-  reflectName _ = fromString (symbolVal (Proxy :: Proxy s))--instance ReflectName 'CacheControl where reflectName _ = "Cache-Control"-instance ReflectName 'Connection where reflectName _ = "Connection"-instance ReflectName 'ContentLength where reflectName _ = "Content-Length"-instance ReflectName 'ContentType where reflectName _ = "Content-Type"-instance ReflectName 'Date where reflectName _ = "Date"-instance ReflectName 'Pragma where reflectName _ = "Pragma"-instance ReflectName 'Upgrade where reflectName _ = "Upgrade"-instance ReflectName 'Via where reflectName _ = "Via"-instance ReflectName 'Warning where reflectName _ = "Warning"-instance ReflectName 'Accept where reflectName _ = "Accept"-instance ReflectName 'AcceptCharset where reflectName _ = "Accept-Charset"-instance ReflectName 'AcceptEncoding where reflectName _ = "Accept-Encoding"-instance ReflectName 'AcceptLanguage where reflectName _ = "Accept-Language"-instance ReflectName 'AccessControlRequestMethod where reflectName _ = "Access-Control-Request-Method"-instance ReflectName 'AccessControlRequestHeaders where reflectName _ = "Access-Control-Request-Headers"-instance ReflectName 'Authorization where reflectName _ = "Authorization"-instance ReflectName 'Cookie where reflectName _ = "Cookie"-instance ReflectName 'Expect where reflectName _ = "Expect"-instance ReflectName 'From where reflectName _ = "From"-instance ReflectName 'Host where reflectName _ = "Host"-instance ReflectName 'IfMatch where reflectName _ = "If-Match"-instance ReflectName 'IfModifiedSince where reflectName _ = "If-Modified-Since"-instance ReflectName 'IfNoneMatch where reflectName _ = "If-None-Match"-instance ReflectName 'IfRange where reflectName _ = "If-Range"-instance ReflectName 'IfUnmodifiedSince where reflectName _ = "If-Unmodified-Since"-instance ReflectName 'MaxForwards where reflectName _ = "Max-Forwards"-instance ReflectName 'Origin where reflectName _ = "Origin"-instance ReflectName 'ProxyAuthorization where reflectName _ = "Proxy-Authorization"-instance ReflectName 'Range where reflectName _ = "Range"-instance ReflectName 'Referer where reflectName _ = "Referer"-instance ReflectName 'TE where reflectName _ = "TE"-instance ReflectName 'UserAgent where reflectName _ = "User-Agent"-instance ReflectName 'XForwardedFor where reflectName _ = "X-Forwarded-For"-instance ReflectName 'XForwardedHost where reflectName _ = "X-Forwarded-Host"-instance ReflectName 'XForwardedProto where reflectName _ = "X-Forwarded-Proto"-instance ReflectName 'XCsrfToken where reflectName _ = "X-Csrf-Token"-instance ReflectName 'AccessControlAllowOrigin where reflectName _ = "Access-Control-Allow-Origin"-instance ReflectName 'AccessControlExposeHeaders where reflectName _ = "Access-Control-Expose-Headers"-instance ReflectName 'AccessControlMaxAge where reflectName _ = "Access-Control-Max-Age"-instance ReflectName 'AccessControlAllowCredentials where reflectName _ = "Access-Control-Allow-Credentials"-instance ReflectName 'AccessControlAllowMethods where reflectName _ = "Access-Control-Allow-Methods"-instance ReflectName 'AccessControlAllowHeaders where reflectName _ = "Access-Control-Allow-Headers"-instance ReflectName 'AcceptPatch where reflectName _ = "Accept-Patch"-instance ReflectName 'AcceptRanges where reflectName _ = "Accept-Ranges"-instance ReflectName 'Age where reflectName _ = "Age"-instance ReflectName 'Allow where reflectName _ = "Allow"-instance ReflectName 'ContentDisposition where reflectName _ = "Content-Disposition"-instance ReflectName 'ContentEncoding where reflectName _ = "Content-Encoding"-instance ReflectName 'ContentLanguage where reflectName _ = "Content-Language"-instance ReflectName 'ContentLocation where reflectName _ = "Content-Location"-instance ReflectName 'ContentRange where reflectName _ = "Content-Range"-instance ReflectName 'ContentSecurityPolicy where reflectName _ = "Content-Security-Policy"-instance ReflectName 'ETag where reflectName _ = "ETag"-instance ReflectName 'Expires where reflectName _ = "Expires"-instance ReflectName 'LastModified where reflectName _ = "Last-Modified"-instance ReflectName 'Link where reflectName _ = "Link"-instance ReflectName 'Location where reflectName _ = "Location"-instance ReflectName 'ProxyAuthenticate where reflectName _ = "Proxy-Authenticate"-instance ReflectName 'PublicKeyPins where reflectName _ = "Public-Key-Pins"-instance ReflectName 'RetryAfter where reflectName _ = "Retry-After"-instance ReflectName 'SetCookie where reflectName _ = "Set-Cookie"-instance ReflectName 'StrictTransportSecurity where reflectName _ = "Strict-Transport-Security"-instance ReflectName 'Trailer where reflectName _ = "Trailer"-instance ReflectName 'TransferEncoding where reflectName _ = "Transfer-Encoding"-instance ReflectName 'Vary where reflectName _ = "Vary"-instance ReflectName 'WWWAuthenticate where reflectName _ = "WWW-Authenticate"
− src/Serv/Internal/Header/Serialization.hs
@@ -1,130 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE TupleSections         #-}--module Serv.Internal.Header.Serialization where--import qualified Data.ByteString           as S-import qualified Data.CaseInsensitive      as CI-import           Data.Proxy-import           Data.Set                  (Set)-import qualified Data.Set                  as Set-import           Data.Text                 (Text)-import qualified Data.Text                 as Text-import qualified Data.Text.Encoding        as Text-import           Data.Time-import           Network.HTTP.Media        (MediaType, Quality, parseQuality)-import qualified Network.HTTP.Types        as HTTP-import           Serv.Internal.Header.Name-import           Serv.Internal.RawText-import           Serv.Internal.Verb---- | Represents mechanisms to interpret data types as header-compatible values.------ An instance of @Encode n t@ captures a mechanism for treating values of type--- @t@ as valid data to substantiate the header @n@.------ Note: While this class allows the encoding of any value into a full Unicode--- Text value, Headers do not generally accept most Unicode code points. Be--- conservative in implementing this class.-class ReflectName n => HeaderEncode (n :: HeaderName) a where-  headerEncode :: Proxy n -> a -> Maybe Text---- | Handles encoding a header all the way to /raw/ bytes.-headerEncodeRaw :: HeaderEncode n a => Proxy n -> a -> Maybe S.ByteString-headerEncodeRaw proxy = fmap Text.encodeUtf8 . headerEncode proxy--instance ReflectName n => HeaderEncode n RawText where-  headerEncode _ (RawText text) = Just text--instance HeaderEncode 'Allow (Set Verb) where-  headerEncode _ verbs =-    Just $ Text.intercalate "," (map (Text.decodeUtf8 . standardName) (Set.toList verbs))--instance HeaderEncode 'Allow [Verb] where-  headerEncode prx verbs = headerEncode prx (Set.fromList verbs)--instance HeaderEncode 'AccessControlExposeHeaders (Set HTTP.HeaderName) where-  headerEncode _ headers =-    Just $ Text.intercalate "," (map (Text.decodeUtf8 . CI.original) (Set.toList headers))--instance HeaderEncode 'AccessControlAllowHeaders (Set HTTP.HeaderName) where-  headerEncode _ headers =-    Just $ Text.intercalate "," (map (Text.decodeUtf8 . CI.original) (Set.toList headers))--instance HeaderEncode 'AccessControlMaxAge NominalDiffTime where-  headerEncode _ ndt = Just $ Text.pack (show (round ndt :: Int))--instance HeaderEncode 'AccessControlAllowOrigin Text where-  headerEncode _ org = Just org--instance HeaderEncode 'AccessControlAllowMethods (Set Verb) where-  headerEncode _ verbs =-    Just $ Text.intercalate "," (map (Text.decodeUtf8 . standardName) (Set.toList verbs))--instance HeaderEncode 'AccessControlAllowMethods [Verb] where-  headerEncode prx verbs = headerEncode prx (Set.fromList verbs)--instance HeaderEncode 'AccessControlAllowCredentials Bool where-  headerEncode _ ok-    | ok = Just "true"-    | otherwise = Just "false"--instance {-# OVERLAPPABLE #-} ReflectName n => HeaderEncode n Bool where-  headerEncode _ ok-    | ok = Just "true"-    | otherwise = Just "false"--instance {-# OVERLAPPABLE #-} ReflectName n => HeaderEncode n Int where-  headerEncode _ i = Just $ Text.pack (show i)--instance {-# OVERLAPPABLE #-} ReflectName n => HeaderEncode n Text where-  headerEncode _ t = Just t--instance {-# OVERLAPPABLE #-} HeaderEncode h t => HeaderEncode h (Maybe t) where-  headerEncode p v = v >>= headerEncode p---- | Represents mechanisms to interpret data types as header-compatible values.------ An instance of @Decode n t@ captures a mechanism for reading values of type--- @t@ from header data stored at header @n@.-class ReflectName n => HeaderDecode (n :: HeaderName) a where-  headerDecode :: Proxy n -> Maybe Text -> Either String a--headerDecode' :: HeaderDecode n a => Proxy n -> Text -> Either String a-headerDecode' p = headerDecode p . Just--required :: (Text -> Either String a) -> Maybe Text -> Either String a-required _ Nothing = Left "missing header value"-required f (Just t) = f t---- | Handles decoding a header all the way from /raw/ bytes.-headerDecodeRaw :: HeaderDecode n a => Proxy n -> Maybe S.ByteString -> Either String a-headerDecodeRaw proxy mays =-  case mays of-    Nothing -> headerDecode proxy Nothing-    Just s ->-      case Text.decodeUtf8' s of-        Left err -> Left (show err)-        Right t -> headerDecode' proxy t---- | 'RawText' enables capturing the data untouched from the header-instance ReflectName n => HeaderDecode n RawText where-  headerDecode _ = required $ \text -> Right (RawText text)--instance HeaderDecode 'Accept [Quality MediaType] where-  headerDecode _ Nothing = Right []-  headerDecode _ (Just text) =-    case parseQuality (Text.encodeUtf8 text) of-      Nothing -> Left "could not parse media type specification"-      Just qs -> Right qs--instance {-# OVERLAPPABLE #-} HeaderDecode h t => HeaderDecode h (Maybe t) where-  headerDecode _ Nothing = Right Nothing-  headerDecode p (Just t) = fmap Just (headerDecode' p t)--headerPair :: HeaderEncode h v => Proxy h -> v -> Maybe HTTP.Header-headerPair proxy v = fmap (reflectName proxy,) (headerEncodeRaw proxy v)
− src/Serv/Internal/MediaType.hs
@@ -1,86 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeOperators         #-}--module Serv.Internal.MediaType where--import qualified Data.ByteString    as S-import           Data.Proxy-import           Network.HTTP.Media (MediaType)-import qualified Network.HTTP.Media as Media--class HasMediaType ty where-  mediaType :: Proxy ty -> MediaType--class HasMediaType ty => MimeEncode ty val where-  mimeEncode :: Proxy ty -> val -> S.ByteString--class HasMediaType ty => MimeDecode ty val where-  mimeDecode :: Proxy ty -> S.ByteString -> Either String val---negotiateContent-  :: ReflectEncoders ctypes a =>-     Proxy ctypes -> [Media.Quality MediaType] -> a -> Maybe (MediaType, S.ByteString)-negotiateContent proxy acceptable value =-  fmap-  (\(mt, encoder) -> (mt, encoder value))-  (Media.mapQuality (map (\(mt, enc) -> (mt, (mt, enc))) $ reflectEncoders proxy) acceptable)---- | Similar to 'negotiateContent' but will always attempt to provide--- the first content type the server offers if nothing is acceptable.--- Still fails when no content types are offered (what's going on?)-negotiateContentAlways-  :: ReflectEncoders ctypes a =>-     Proxy ctypes -> [Media.Quality MediaType] -> a -> Maybe (MediaType, S.ByteString)-negotiateContentAlways proxy acceptable value =-  case negotiateContent proxy acceptable value of-    Nothing -> case reflectEncoders proxy of-      [] -> Nothing-      ((mt, encoder) : _) -> Just (mt, encoder value)-    Just result -> Just result--class ReflectEncoders cts ty where-  reflectEncoders :: Proxy cts -> [(MediaType, ty -> S.ByteString)]--instance ReflectEncoders '[] ty where-  reflectEncoders Proxy = []--instance-  (ReflectEncoders cts ty, MimeEncode ct ty) =>-    ReflectEncoders (ct ': cts) ty-  where-    reflectEncoders Proxy =-      (mediaType pCt, mimeEncode pCt) : reflectEncoders pCts-      where-        pCt = Proxy :: Proxy ct-        pCts = Proxy :: Proxy cts---tryDecode-  :: ReflectDecoders ctypes a =>-     Proxy ctypes -> S.ByteString -> S.ByteString -> Maybe (Either String a)-tryDecode proxy mt body =-  fmap-  (\decoder -> decoder body)-  (Media.mapContentMedia (reflectDecoders proxy) mt)--class ReflectDecoders cts ty where-  reflectDecoders :: Proxy cts -> [(MediaType, S.ByteString -> Either String ty)]--instance ReflectDecoders '[] ty where-  reflectDecoders Proxy = []--instance-  (MimeDecode ct ty, ReflectDecoders cts ty) =>-    ReflectDecoders (ct ': cts) ty-  where-    reflectDecoders Proxy =-      (mediaType pCt, mimeDecode pCt) : reflectDecoders pCts-      where-        pCt = Proxy :: Proxy ct-        pCts = Proxy :: Proxy cts
− src/Serv/Internal/Pair.hs
@@ -1,11 +0,0 @@-{-# LANGUAGE DataKinds     #-}-{-# LANGUAGE PolyKinds     #-}-{-# LANGUAGE TypeOperators #-}--module Serv.Internal.Pair where---- | Equivalent to a tuple at both the type and kind levels,--- but has a nicer syntax!-data Pair a b = a ::: b--infixr 6 :::
− src/Serv/Internal/Query.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeOperators         #-}--module Serv.Internal.Query where--import           Data.Proxy-import           Data.String-import           Data.Text             (Text)-import           Data.Text.Encoding    (encodeUtf8)-import           GHC.TypeLits-import qualified Network.HTTP.Types    as HTTP-import           Serv.Internal.Pair-import           Serv.Internal.RawText-import           Serv.Internal.Rec--class QueryEncode (s :: Symbol) a where-  queryEncode :: Proxy s -> a -> Maybe Text--class QueryDecode (s :: Symbol) a where-  queryDecode :: Proxy s -> Maybe Text -> Either String a--instance QueryEncode s RawText where-  queryEncode _ (RawText t) = Just t--instance QueryDecode s RawText where-  queryDecode _ Nothing = Left "expected query value"-  queryDecode _ (Just t) = Right (RawText t)---- | Given a record of headers, encode them into a list of header pairs.-class ReflectQuery query where-  reflectQuery :: Rec query -> HTTP.Query--instance ReflectQuery '[] where-  reflectQuery Nil = []--instance-  (KnownSymbol s, QueryEncode s a, ReflectQuery query) =>-    ReflectQuery ( s '::: a ': query )-  where-    reflectQuery (Cons val rest) = (name, value) : reflectQuery rest-      where-        proxy = Proxy :: Proxy s-        name = fromString (symbolVal proxy)-        value = encodeUtf8 <$> queryEncode proxy val
− src/Serv/Internal/RawText.hs
@@ -1,16 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Serv.Internal.RawText where--import           Data.String-import           Data.Text   (Text)---- | RawText extracts as, like the name suggests,--- raw text from URI segments and header values.------ It exists as a default value for extensibility of typeclasses like--- HeaderDecode and HeaderEncode--newtype RawText =-  RawText { getRawText :: Text }-  deriving (Eq, Ord, Read, Show, Monoid, IsString)
− src/Serv/Internal/Rec.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeOperators         #-}-{-# LANGUAGE UndecidableInstances  #-}--module Serv.Internal.Rec where--import           Data.Proxy-import           Data.Tagged-import           Serv.Internal.Pair---- | An HList collecting heterogenous types matched up to labeling information-data Rec rs where-  Nil :: Rec '[]-  Cons :: ty -> Rec rs -> Rec ( name '::: ty ': rs )---- | Append a new header value on to a record-(-:) :: Proxy name -> ty -> Rec rs -> Rec (name '::: ty ': rs)-(-:) _ = Cons--class Elem name e es where-  eGet :: Rec es -> Tagged name e-  eMap :: Tagged name (e -> e) -> Rec es -> Rec es--instance {-# OVERLAPPING #-} Elem name e (name '::: e ': rs) where-  eGet (Cons x _) = Tagged x-  eMap (Tagged f) (Cons x rs) = Cons (f x) rs--instance {-# OVERLAPPABLE #-} Elem name e rs => Elem name e (r ': rs) where-  eGet (Cons _ rs) = eGet rs-  eMap f (Cons x rs) = Cons x (eMap f rs)--class Subset rs qs where-  project :: Rec qs -> Rec rs--instance Subset '[] qs where-  project _ = Nil--instance (Elem name r qs, Subset rs qs) => Subset (name '::: r ': rs) qs where-  project r =-    let Tagged v = (eGet r :: Tagged name r)-    in Cons v (project r)--class RecordIso rs qs where-  reorder :: Rec rs -> Rec qs--instance (Subset rs qs, Subset qs rs) => RecordIso rs qs where-  reorder = project
− src/Serv/Internal/Server.hs
@@ -1,319 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE MultiWayIf            #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}--module Serv.Internal.Server where--import           Data.Function                ((&))-import           Data.Maybe-import           Data.Proxy-import           Data.Set                     (Set)-import qualified Data.Set                     as Set-import           Data.String-import           Data.Tagged-import           Data.Text                    (Text)-import           GHC.TypeLits-import qualified Network.HTTP.Types           as HTTP-import qualified Network.Wai                  as Wai-import qualified Serv.Header.Proxies          as Hp-import           Serv.Internal.Api-import           Serv.Internal.Api.Analysis-import qualified Serv.Internal.Cors           as Cors-import qualified Serv.Internal.Header         as Header-import           Serv.Internal.Pair-import           Serv.Internal.Rec-import           Serv.Internal.Server.Context (Context)-import qualified Serv.Internal.Server.Context as Context-import qualified Serv.Internal.Server.Error   as Error-import           Serv.Internal.Server.Type-import qualified Serv.Internal.URI            as URI-import qualified Serv.Internal.Verb           as Verb---- Handling--- -------------------------------------------------------------------------------- | The the core type function responsible for interpreting an 'Api' into a--- functioning 'Server'. It defines a function 'handle' defined over all forms--- of 'Api' types which consumes a parallel type defined by the associated--- type family 'Impl'. If @api :: Api@ then @Impl api m@ is an "implementation"--- of the 'Api''s server logic executing in the @m@ monad. Then, applying--- 'handle' to a value of @'Impl' api@ results in a 'Server' which can be--- executed as a 'Wai.Application'.--class Handling (spec :: k) where-  type Impl spec (m :: * -> *)-  handle :: Monad m => Proxy spec -> Impl spec m -> Server m--{---TODO-------- [X] 'Method verb headers body-- [T] 'CaptureHeaders headers api-- [T] 'CaptureQuery query api-- [T] 'CaptureBody ctypes value api-- [X] 'Raw--- [X] '[]-- [X] x ': xs--- [X] OneOf apis-- [X] Endpoint apis--- [X] Const s :> api-- [X] HeaderAs name value :> api-- [X] Seg name value :> api-- [X] Header name value :> api-- [X] Wildcard :> api-- [ ] Flag name :> api-- [ ] QueryParam name value :> api-- [X] Cors :> api---}--encodeBody :: WaiResponse hdrs body => Context -> Response hdrs body -> ServerValue-encodeBody ctx resp =-  case acceptHdr of-    Left _ -> WaiResponse (waiResponse [] resp)-    Right acceptList ->-      WaiResponse (waiResponse acceptList resp)-  where-    (_, acceptHdr) = Context.examineHeader Hp.accept ctx---- | 'GET' is special-cased to handle @HEAD@ semantics which cannot be--- specified otherwise.-instance-  {-# OVERLAPPING  #-}-  WaiResponse headers body =>-  Handling ('Method 'Verb.GET headers body) where--  type Impl ('Method 'Verb.GET headers body) m =-    m (Response headers body)--  handle _ mresp = Server $ \ctx -> do-    let method = Context.method ctx-    case method of-      "GET" -> do-        resp <- mresp-        return (encodeBody ctx resp)-      "HEAD" -> do-        resp <- mresp-        let newResp = deleteBody resp-        return (WaiResponse (waiResponse [] newResp))-      _ -> routingError Error.NotFound--instance-  (Verb.ReflectVerb verb, WaiResponse headers body) =>-  Handling ('Method verb headers body) where--  type Impl ('Method verb headers body) m =-    m (Response headers body)--  handle _ mresp = Server $ \ctx -> do-    let method = Context.method ctx-        expected = Verb.reflectVerb (Proxy :: Proxy verb)-    if method /= Verb.standardName expected-       then routingError Error.NotFound-       else do-         resp <- mresp-         case snd (Context.examineHeader Hp.accept ctx) of-           Left _err ->-             routingError-             (Error.BadRequest-              (Just "could not parse acceptable content types"))-           Right accepts ->-             return (WaiResponse $ waiResponse accepts resp)--instance Handling method =>-  Handling ('CaptureHeaders (headers :: [Pair Header.HeaderName *]) method) where-  type Impl ('CaptureHeaders headers method) m =-    Rec headers -> Impl method m-  handle = undefined -- TODO--instance Handling method =>-  Handling ('CaptureQuery (query :: [Pair Symbol *]) method) where-  type Impl ('CaptureQuery query method) m =-    Rec query -> Impl method m-  handle = undefined -- TODO--instance Handling method =>-  Handling ('CaptureBody ctypes (value :: *) method) where-  type Impl ('CaptureBody ctypes value method) m =-    value -> Impl method m-  handle = undefined -- TODO--instance Handling 'Raw where-  type Impl 'Raw m = m Wai.Application-  handle _ impl = Server $ \_ -> do-    app <- impl-    return (Application app)--instance-  (VerbsOf methods,-   HeadersReturnedBy methods,-   HeadersExpectedOf methods,-   Handling methods)-  => Handling ('Endpoint (methods :: [Method *]))-  where-    type Impl ('Endpoint methods) m = Impl methods m-    handle Proxy impl = Server $ \ctx -> do-      let pathIsEmpty = Context.pathIsEmpty ctx-      if not pathIsEmpty-        then routingError Error.NotFound-        else do-          let method = Context.method ctx-              methodsProxy = Proxy :: Proxy methods-          if | method == HTTP.methodOptions ->-                 return $ defaultOptionsResponse verbs-                        & addHeaders (-                            fromMaybe [] $ Context.corsHeaders methodsProxy True ctx-                          )--             | verbMatch verbs method -> do-                 value <- runServer (handle (Proxy :: Proxy methods) impl) ctx-                 return $ value-                        & addHeaders (-                            fromMaybe [] $ Context.corsHeaders methodsProxy False ctx-                          )--             | otherwise ->-               -- TODO: Probably a double-check; trying the method implementations-               -- ought to fail this way, too-               routingError (Error.MethodNotAllowed (Set.toList verbs))-      where-        verbs = verbsOf (Proxy :: Proxy methods)-        addHeaders hdrs v =-          case v of-            WaiResponse resp ->-              WaiResponse (Wai.mapResponseHeaders (hdrs ++) resp)-            other -> other----- | Is the request method in the set of verbs?-verbMatch :: Set Verb.Verb -> HTTP.Method -> Bool-verbMatch verbs methodname =-    case methodname of-      -- Special-casing the GET/HEAD overlap-      "HEAD" -> verbMatch verbs "GET"-      _ -> methodname `Set.member` Set.map Verb.standardName verbs--defaultOptionsResponse :: Set Verb.Verb -> ServerValue-defaultOptionsResponse verbs =-  -- TODO: Add CORS information-  WaiResponse-  $ Wai.responseLBS-    HTTP.ok200-    (catMaybes [Header.headerPair Hp.allow orderedVerbs])-    ""-  where-    allVerbs =-      if Set.member Verb.GET verbs-        then verbs & Set.insert Verb.HEAD-                   & Set.insert Verb.OPTIONS-        else verbs & Set.insert Verb.OPTIONS-    orderedVerbs = Set.toList allVerbs--instance Handling '[] where-  type Impl '[] m = m NotHere-  handle _ m = Server $ \_ -> do-    NotHere <- m-    routingError Error.NotFound--instance (Handling x, Handling xs) => Handling (x ': xs) where-  type Impl (x ': xs) m = Impl x m :<|> Impl xs m-  handle _ (l :<|> r) = lServer `orElse` rServer where-    lServer = handle (Proxy :: Proxy x) l-    rServer = handle (Proxy :: Proxy xs) r--instance Handling apis => Handling ('OneOf apis) where-  type Impl ('OneOf apis) m = Impl apis m-  handle _ = handle (Proxy :: Proxy apis)--instance (KnownSymbol s, Handling api) => Handling ('Const s ':> api) where-  type Impl ('Const s ':> api) m = Impl api m-  handle _ impl = Server $ \ctx -> do-    let (ctx', m) = Context.takeSegment ctx-        matchName = fromString (symbolVal (Proxy :: Proxy s))-        next = handle (Proxy :: Proxy api) impl-    case m of-      Nothing -> routingError Error.NotFound-      Just seg-        | seg /= matchName -> routingError Error.NotFound-        | otherwise -> runServer next ctx'--instance Handling api => Handling ('Wildcard ':> api) where-  type Impl ('Wildcard ':> api) m = [Text] -> Impl api m-  handle _ f = Server $ \ctx -> do-    let (ctx', segs) = Context.takeAllSegments ctx-    runServer (handle (Proxy :: Proxy api) (f segs)) ctx'--instance (Header.ReflectName n, KnownSymbol v, Handling api) => Handling ('HeaderAs n v ':> api) where-  type Impl ('HeaderAs s v ':> api) m = Impl api m-  handle _ impl = Server $ \ctx -> do-    let headerProxy = Proxy :: Proxy n-        headerValue = fromString (symbolVal (Proxy :: Proxy v))-        next = handle (Proxy :: Proxy api) impl-        (ctx', ok) = Context.expectHeader headerProxy headerValue ctx-    if ok-      then runServer next ctx'-      else routingError Error.NotFound--instance-  (Header.HeaderDecode n v, Handling api) => Handling ('Header n v ':> api)-  where-    type Impl ('Header n v ':> api) m = v -> Impl api m-    handle _ impl = Server $ \ctx -> do-      let headerProxy = Proxy :: Proxy n-          (ctx', m) = Context.examineHeader headerProxy ctx-          next = handle (Proxy :: Proxy api) . impl-      case m of-        Left parseError -> routingError (Error.BadRequest (Just parseError))-        Right value -> runServer (next value) ctx'--instance (URI.URIDecode v, Handling api) => Handling ('Seg n v ':> api) where-  type Impl ('Seg n v ':> api) m = Tagged n v -> Impl api m-  handle _ impl = Server $ \ctx -> do-    let (ctx', m) = Context.takeSegment ctx-        next = handle (Proxy :: Proxy api) . impl-    case m of-      Nothing -> routingError Error.NotFound-      Just seg -> case URI.uriDecode seg of-        Left _err -> routingError (Error.BadRequest Nothing)-        Right val -> runServer (next $ Tagged val) ctx'--instance (Handling api, Cors.CorsPolicy p) => Handling ('Cors p ':> api) where-  type Impl ('Cors p ':> api) m = Impl api m-  handle _ impl = Server $ \ctx ->-    let newCtx = ctx { Context.corsPolicies =-                         Cors.corsPolicy (Proxy :: Proxy p)-                         : Context.corsPolicies ctx }-    in runServer (handle (Proxy :: Proxy api) impl) newCtx---- instance (ContentMatching cts ty, Handling api) => Handling ('CaptureBody cts ty ':> api) where----   type Impl ('CaptureBody cts ty ':> api) m =---     ty -> Impl api m----   handle Proxy impl = Server $ do---     (newContext, maybeHeader) <- asks $ Context.pullHeaderRaw HTTP.hContentType---     let header = fromMaybe "application/octet-stream" maybeHeader---     reqBody <- asks Context.body---     case Media.mapContentMedia matches header of---       Nothing -> throwError Error.UnsupportedMediaType---       Just decoder -> case decoder reqBody of---         Left err -> throwError $ Error.BadRequest (Just err)---         Right val -> local (const newContext) (continue val)----     where---       matches = contentMatch (Proxy :: Proxy cts)---       continue = runServer . handle (Proxy :: Proxy api) . impl
− src/Serv/Internal/Server/Config.hs
@@ -1,8 +0,0 @@--module Serv.Internal.Server.Config where--data Config =-  Config--defaultConfig :: Config-defaultConfig = Config
− src/Serv/Internal/Server/Context.hs
@@ -1,178 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE PolyKinds             #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}--module Serv.Internal.Server.Context where--import qualified Data.ByteString             as S-import qualified Data.ByteString.Lazy        as Sl-import qualified Data.IORef                  as IORef-import           Data.Monoid-import           Data.Proxy-import           Data.Set                    (Set)-import qualified Data.Set                    as Set-import           Data.Text                   (Text)-import qualified Network.HTTP.Types          as HTTP-import qualified Network.Wai                 as Wai-import qualified Serv.Header.Proxies         as Hp-import qualified Serv.Internal.Api.Analysis  as Analysis-import qualified Serv.Internal.Cors          as Cors-import qualified Serv.Internal.Header        as Header-import           Serv.Internal.RawText-import           Serv.Internal.Server.Config-import qualified Serv.Internal.URI           as URI--data Context =-  Context-  { request         :: Wai.Request-  , pathZipper      :: ([Text], [Text])-  , headersExpected :: [(HTTP.HeaderName, Maybe Text)]-  , config          :: Config--    -- cached via strictRequestBody so that we don't have to deal with multiple-    -- request body pulls affecting one another; this defeats partial and lazy body-    -- loading, BUT the style of API description we're talking about here isn't really-    -- amenable to that sort of thing anyway.-    ---    -- also note that we really need to compute this using Lazy IO; otherwise,-    -- we'll have to be handling the partial request/respond dance from the get-go.--  , body            :: S.ByteString--  , corsPolicies :: [Cors.Policy]-  }--corsHeaders-  :: (Analysis.HeadersExpectedOf methods,-     Analysis.HeadersReturnedBy methods,-     Analysis.VerbsOf methods)-  => Proxy methods -> Bool -> Context -> Maybe [HTTP.Header]-corsHeaders proxy includeMethods ctx = do-  let derivedExpected = Analysis.headersExpectedOf proxy-      derivedReturned = Analysis.headersReturnedBy proxy-      derivedVerbs = Analysis.verbsOf proxy-      policyChain = corsPolicies ctx-      conf = config ctx-  RawText origin <- examineHeaderFast Hp.origin ctx-  let corsContext =-        Cors.Context-        { Cors.origin = origin-        , Cors.headersExpected =-            Set.fromList (map fst (headersExpected ctx))-            <> derivedExpected-        , Cors.headersReturned = derivedReturned-        , Cors.methodsAvailable = derivedVerbs-        }-  let accessSet = foldMap (\p -> p conf corsContext) policyChain-  return (Cors.headerSet includeMethods corsContext accessSet)--makeContext :: Config -> Wai.Request -> IO Context-makeContext theConfig theRequest = do-  theBody <- Wai.strictRequestBody theRequest-  -- We create a "frozen", strict version of the body and augment the request to-  -- always return it directly.-  ref <- IORef.newIORef (Sl.toStrict theBody)-  return Context { request = theRequest { Wai.requestBody = IORef.readIORef ref }-                 , config = theConfig-                 , body = Sl.toStrict theBody-                 , pathZipper = ([], Wai.pathInfo theRequest)-                 , headersExpected = []-                 , corsPolicies = []-                 }--pathIsEmpty :: Context -> Bool-pathIsEmpty ctx = case pathZipper ctx of-  (_, []) -> True-  _ -> False--method :: Context -> HTTP.Method-method = Wai.requestMethod . request--requestHeadersSeen :: Context -> Set HTTP.HeaderName-requestHeadersSeen = Set.fromList . map fst . headersExpected---- | Pop all remaining segments off the context-takeAllSegments :: Context -> (Context, [Text])-takeAllSegments ctx = (newContext, fore) where-  newContext = ctx { pathZipper = (reverse fore ++ hind, []) }-  (hind, fore) = pathZipper ctx---- | Pop a segment off the URI and produce a new context for "beyond" that segment-takeSegment :: Context -> (Context, Maybe Text)-takeSegment ctx = (stepContext ctx, safeHead fore) where-  (_, fore) = pathZipper ctx---- | Move the context down the URI segment listing one step if possible.-stepContext :: Context -> Context-stepContext ctx =-  case fore of-    [] -> ctx-    seg : rest -> ctx { pathZipper = (seg : hind, rest) }--  where-    (hind, fore) = pathZipper ctx---- | Pull a Header raw from the context, updating it to note that we looked-pullHeaderRaw :: HTTP.HeaderName -> Context -> (Context, Maybe S.ByteString)-pullHeaderRaw name ctx =-  (newContext, lookup name headers)-  where-    newContext = ctx { headersExpected = (name, Nothing) : headersExpected ctx }-    headers = Wai.requestHeaders req-    req = request ctx---- | Pull a header value from the context, updating it to note that we looked-examineHeader-  :: Header.HeaderDecode n a-     => Proxy n -> Context -> (Context, Either String a)-examineHeader proxy ctx =-  (newContext, Header.headerDecodeRaw proxy rawString)-  where-    headerName = Header.reflectName proxy-    (newContext, rawString) = pullHeaderRaw headerName ctx---- | Sort of like 'examineHeader' but used for when we just want the value--- and don't care about updating the context or worrying about--- distinguishing between decoding failure and outright not being there at--- all!-examineHeaderFast :: Header.HeaderDecode n a => Proxy n -> Context -> Maybe a-examineHeaderFast proxy ctx =-  let (_, hdr) = pullHeaderRaw (Header.reflectName proxy) ctx-  in hush (Header.headerDecodeRaw proxy hdr)-  where-    hush :: Either e a -> Maybe a-    hush (Left _) = Nothing-    hush (Right a) = Just a---- | Match a header value in the context, updating it to show that we looked-expectHeader :: Header.ReflectName n => Proxy n -> Text -> Context -> (Context, Bool)-expectHeader proxy value ctx =-  (newContext, valOk)--  where-    valOk =-      case fmap URI.fromByteString mayVal of-        Nothing -> False-        Just (Left _) -> False-        Just (Right (RawText observation)) -> observation == value--    headerName = Header.reflectName proxy-    mayVal = lookup headerName headers-    newContext = ctx { headersExpected = (headerName, Just value) : headersExpected ctx }-    headers = Wai.requestHeaders req-    req = request ctx---- Util--- ------------------------------------------------------------------------------safeHead :: [a] -> Maybe a-safeHead [] = Nothing-safeHead (a : _) = Just a
− src/Serv/Internal/Server/Error.hs
@@ -1,17 +0,0 @@--module Serv.Internal.Server.Error where--import           Serv.Internal.Verb---- | Errors which arise during the "handling" portion of dealing with a response.-data RoutingError-  = NotFound-  | BadRequest (Maybe String)-  | UnsupportedMediaType-  | MethodNotAllowed [Verb]---- | An ignorable error is one which backtracks the routing search--- instead of forcing a response.-ignorable :: RoutingError -> Bool-ignorable NotFound = True-ignorable _ = False
− src/Serv/Internal/Server/Type.hs
@@ -1,221 +0,0 @@-{-# LANGUAGE DataKinds             #-}-{-# LANGUAGE RankNTypes            #-}-{-# LANGUAGE KindSignatures        #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE GADTs                 #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings     #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeOperators         #-}--module Serv.Internal.Server.Type where--import Data.String-import Data.Maybe (fromMaybe)-import qualified Data.ByteString.Char8         as S8-import qualified Data.ByteString.Lazy         as Sl-import           Data.Function                ((&))-import           Data.Proxy-import           Network.HTTP.Media           (MediaType, Quality, renderHeader)-import qualified Network.HTTP.Types           as HTTP-import qualified Network.Wai                  as Wai-import           Serv.Internal.Api-import qualified Serv.Internal.Header         as Header-import qualified Serv.Internal.MediaType      as MediaType-import           Serv.Internal.Pair-import           Serv.Internal.Rec-import qualified Serv.Internal.Verb as Verb-import           Serv.Internal.Server.Context (Context)-import qualified Serv.Internal.Server.Context as Context-import           Serv.Internal.Server.Error   (RoutingError)-import qualified Serv.Internal.Server.Error   as Error---- | A server implementation which always results in a "Not Found" error. Used to--- give semantics to "pathological" servers like @'OneOf '[]@ and @Endpoint '[]@.------ These servers could be statically disallowed but (1) they have a semantic--- sense as described by this type exactly and (2) to do so would require the--- creation and management of either larger types or non-empty proofs which would--- be burdensome to carry about.-data NotHere = NotHere---- | Actual servers are implemented effectfully; this is a no-op server which--- immediately returns Not Found and applies no effects.-noOp :: Applicative m => m NotHere-noOp = pure NotHere---- | Either one thing or the other. In particular, often this is used when we are--- describing either one server implementation or the other. Used to give--- semantics to @'OneOf@ and @'Endpoint@.-data a :<|> b = a :<|> b--infixr 5 :<|>---- | A return value from a 'Server' computation.-data ServerValue-  = RoutingError RoutingError-    -- ^ Routing errors arise when a routing attempt fails and, depending on the-    -- error, either we should recover and backtrack or resolve the entire response-    -- with that error.-  | WaiResponse Wai.Response-    -- ^ If the response is arising from the 'Server' computation itself it will-    -- be transformed automatically into a 'Wai.Response' value we can handle-    -- directly. These are opaque to routing, assumed successes.-  | Application Wai.Application-    -- ^ If the application demands an "upgrade" or ties into another server-    -- mechanism then routing at that location will return the (opaque)-    -- 'Application' to continue handling.--runServerWai-  :: Context-  -> (Wai.Response -> IO Wai.ResponseReceived)-  -> (Server IO -> IO Wai.ResponseReceived)-runServerWai context respond server = do-  val <- runServer server context-  case val of-    RoutingError err -> respond $ case err of-      Error.NotFound ->-        Wai.responseLBS HTTP.notFound404 [] ""-      Error.BadRequest e -> do-        let errString = fromString (fromMaybe "" e)-        Wai.responseLBS HTTP.badRequest400 [] (fromString errString)-      Error.UnsupportedMediaType ->-        Wai.responseLBS HTTP.unsupportedMediaType415 [] ""-      Error.MethodNotAllowed verbs -> do-        let verbNames = map Verb.standardName verbs-            allowHeader = S8.intercalate "," verbNames-        Wai.responseLBS HTTP.methodNotAllowed405 [("Allow", allowHeader)] ""--    WaiResponse resp -> respond resp--    -- We forward the request (frozen) and the respond handler-    -- on to the internal application-    Application app -> app (Context.request context) respond---- A server executing in a given monad. We construct these from 'Api'--- descriptions and corresponding 'Impl' descriptions for said 'Api's.--- Ultimately, a 'Server', or at least a 'Server IO', is destined to be--- transformed into a Wai 'Wai.Appliation', but 'Server' tracks around more--- information useful for interpretation and route finding.-newtype Server m = Server { runServer :: Context -> m ServerValue }---- Lift an effect transformation on to a Server-transformServer :: (forall x . m x -> n x) -> Server m -> Server n-transformServer phi (Server act) = Server (phi . act)---- | 'Server's form a semigroup trying each 'Server' in order and receiving--- the leftmost one which does not end in an ignorable error.------ Or, with less technical jargon, @m `orElse` n@ acts like @m@ except in the--- case where @m@ returns an 'Error.ignorable' 'Error.Error' in which case control--- flows on to @n@.-orElse :: Monad m => Server m -> Server m -> Server m-orElse sa sb = Server $ \ctx -> do-  a <- runServer sa ctx-  case a of-    RoutingError e-      | Error.ignorable e -> runServer sb ctx-      | otherwise -> return a-    _ -> return a--routingError :: Monad m => RoutingError -> m ServerValue-routingError err = return (RoutingError err)---- Responses--- -------------------------------------------------------------------------------- | Responses generated in 'Server' implementations.-data Response (headers :: [Pair Header.HeaderName *]) body where-  Response-    :: HTTP.Status-    -> [HTTP.Header]-    -> Rec headers-    -> a-    -> Response headers ('Body ctypes a)-  EmptyResponse-    :: HTTP.Status-    -> [HTTP.Header]-    -> Rec headers-    -> Response headers 'Empty---- An 'emptyResponse' returns the provided status message with no body or headers-emptyResponse :: HTTP.Status -> Response '[] 'Empty-emptyResponse status = EmptyResponse status [] Nil---- | Adds a body to a response-withBody-  :: a -> Response headers 'Empty -> Response headers ('Body ctypes a)-withBody a (EmptyResponse status secretHeaders headers) =-  Response status secretHeaders headers a---- | Adds a header to a response-withHeader-  :: Proxy name -> value-  -> Response headers body -> Response (name '::: value ': headers) body-withHeader proxy val r = case r of-  Response status secretHeaders headers body ->-    Response status secretHeaders (headers & proxy -: val) body-  EmptyResponse status secretHeaders headers ->-    EmptyResponse status secretHeaders (headers & proxy -: val)---- | Unlike 'withHeader', 'withQuietHeader' allows you to add headers--- not explicitly specified in the api specification.-withQuietHeader-  :: Header.HeaderEncode name value-     => Proxy name -> value-     -> Response headers body -> Response headers body-withQuietHeader proxy value r =-  case Header.headerPair proxy value of-    Nothing -> r-    Just newHeader ->-      case r of-        Response status secretHeaders headers body ->-          Response status (newHeader : secretHeaders) headers body-        EmptyResponse status secretHeaders headers ->-          EmptyResponse status (newHeader : secretHeaders) headers---- | If a response type is complete defined by its implementation then--- applying 'resorted' to it will future proof it against reorderings--- of headers. If the response type is not completely inferrable, however,--- then this will require manual annotations of the "pre-sorted" response.-resortHeaders :: RecordIso headers headers' => Response headers body -> Response headers' body-resortHeaders r =-  case r of-    Response status secretHeaders headers body ->-      Response status secretHeaders (reorder headers) body-    EmptyResponse status secretHeaders headers ->-      EmptyResponse status secretHeaders (reorder headers)---- | Used primarily for implementing @HEAD@ request automatically.-deleteBody :: Response headers body -> Response headers 'Empty-deleteBody r =-  case r of-    Response status secretHeaders headers _ ->-      EmptyResponse status secretHeaders headers-    EmptyResponse{} -> r---- Reflection--- -------------------------------------------------------------------------------- TODO: This is quite weird. It'd be better to have ReflectHeaders show up--- in fewer places--class Header.ReflectHeaders headers => WaiResponse headers body where-  waiResponse :: [Quality MediaType] -> Response headers body -> Wai.Response--instance Header.ReflectHeaders headers => WaiResponse headers 'Empty where-  waiResponse _ (EmptyResponse status secretHeaders headers) =-    Wai.responseLBS status (secretHeaders ++ Header.reflectHeaders headers) ""--instance-  (Header.ReflectHeaders headers, MediaType.ReflectEncoders ctypes a) =>-    WaiResponse headers ('Body ctypes a)-  where-    waiResponse accepts (Response status secretHeaders headers value) =-      case MediaType.negotiateContentAlways (Proxy :: Proxy ctypes) accepts value of-        Nothing -> Wai.responseLBS HTTP.notAcceptable406 [] ""-        Just (mtChosen, result) ->-          let headers0 = Header.reflectHeaders headers-              headers1 = ("Content-Type", renderHeader mtChosen) : headers0-              headers2 = secretHeaders ++ headers1-          in Wai.responseLBS status headers2 $ Sl.fromStrict result
− src/Serv/Internal/URI.hs
@@ -1,21 +0,0 @@--module Serv.Internal.URI where--import qualified Data.ByteString.Char8 as S8-import           Data.Text             (Text)-import qualified Data.Text.Encoding    as Enc-import           Serv.Internal.RawText--class URIEncode a where-  uriEncode :: a -> Text--class URIDecode a where-  uriDecode :: Text -> Either String a--instance URIDecode RawText where-  uriDecode text = Right (RawText text)--fromByteString :: URIDecode a => S8.ByteString -> Either String a-fromByteString s = case Enc.decodeUtf8' s of-  Left _err -> Left "could not parse UTF8 string"-  Right a -> uriDecode a
− src/Serv/Internal/Verb.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE DataKinds      #-}-{-# LANGUAGE KindSignatures #-}--module Serv.Internal.Verb where--import           Data.Proxy-import qualified Network.HTTP.Types as HTTP---- TRACE is intentionally omitted because (a) it's very low value and (b)--- it opens a potential security hole via Cross-Site-Tracing. Instead of--- even evaluating that risk we'll just disallow it.--data Verb-  = DELETE-  | GET-  | HEAD-  | OPTIONS-  | PATCH-  | POST-  | PUT-    deriving ( Eq, Ord, Show, Read )--standardName :: Verb -> HTTP.Method-standardName v = case v of-  GET -> HTTP.methodGet-  HEAD -> HTTP.methodHead-  POST -> HTTP.methodPost-  PUT -> HTTP.methodPut-  PATCH -> HTTP.methodPatch-  DELETE -> HTTP.methodDelete-  OPTIONS -> HTTP.methodOptions--class ReflectVerb (v :: Verb) where-  reflectVerb :: Proxy v -> Verb--instance ReflectVerb 'GET where reflectVerb Proxy = GET-instance ReflectVerb 'HEAD where reflectVerb Proxy = HEAD-instance ReflectVerb 'POST where reflectVerb Proxy = POST-instance ReflectVerb 'PUT where reflectVerb Proxy = PUT-instance ReflectVerb 'PATCH where reflectVerb Proxy = PATCH-instance ReflectVerb 'DELETE where reflectVerb Proxy = DELETE-instance ReflectVerb 'OPTIONS where reflectVerb Proxy = OPTIONS
− src/Serv/Server.hs
@@ -1,44 +0,0 @@--module Serv.Server (--    Server-    , transformServer-    , makeApplication--    , Config-    , defaultConfig--    , Handling (handle)-    , Impl--      -- For implementation-    , (:<|>) (..), NotHere (..)-    , noOp--    , Response-    , emptyResponse-    , withBody-    , withHeader-    , withQuietHeader--      -- HTTP Status re-exports-    , module Network.HTTP.Types.Status-    , module Data.Tagged---  ) where--import           Data.Tagged-import           Network.HTTP.Types.Status-import qualified Network.Wai                  as Wai-import           Serv.Internal.Server-import           Serv.Internal.Server.Config-import           Serv.Internal.Server.Context-import           Serv.Internal.Server.Type---- | Build a 'Wai.Application' from an implemented @'Server' 'IO'@.-makeApplication :: Config -> Server IO -> Wai.Application-makeApplication conf server = app where-  app req resp = do-    ctx <- makeContext conf req-    runServerWai ctx resp server
− src/Serv/URI.hs
@@ -1,9 +0,0 @@--module Serv.URI (--    URIEncode (..)-  , URIDecode (..)--  ) where--import Serv.Internal.URI
− test/Examples/Ex1.hs
@@ -1,111 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators     #-}--module Examples.Ex1 where--import           Data.Function       ((&))-import           Data.Proxy-import           Data.String-import           Data.Text           (Text)-import qualified Network.Wai         as Wai-import qualified Network.Wai.Test    as T-import qualified Serv.Api            as A-import           Serv.Common-import qualified Serv.ContentType    as Ct-import qualified Serv.Header         as H-import qualified Serv.Header.Proxies as Hp-import           Serv.Server-import           Test.Tasty-import qualified Test.Tasty.HUnit    as Hu--type RawBody = 'A.Body '[ Ct.TextPlain ] Text-type JSONBody = 'A.Body '[ Ct.JSON ] [Int]--type Api-  = 'A.Endpoint-    '[ 'A.Method 'A.GET '[ 'H.CacheControl 'A.::: RawText ] RawBody-     , 'A.Method 'A.PUT '[ 'H.CacheControl 'A.::: RawText ] JSONBody-     ]--apiProxy :: Proxy Api-apiProxy = Proxy--impl :: Impl Api IO-impl = get :<|> put :<|> noOp-  where-    get =-      return-      $ emptyResponse ok200-      & withHeader Hp.cacheControl "foo"-      & withBody "Hello"-    put =-      return-      $ emptyResponse ok200-      & withHeader Hp.cacheControl "foo"-      & withBody [1, 2, 3]---server :: Server IO-server = handle apiProxy impl--runTest :: T.Session a -> IO a-runTest = flip T.runSession (makeApplication defaultConfig server)--test1 :: TestTree-test1 = testGroup "Simple responses"-  [ Hu.testCase "Constant GET response (RawText)" $ runTest $ do-      let req = Wai.defaultRequest-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertContentType "text/plain" resp-      T.assertBody "Hello" resp-      T.assertHeader "Cache-Control" "foo" resp--  , Hu.testCase "Constant PUT response (JSON)" $ runTest $ do-      let req = Wai.defaultRequest { Wai.requestMethod = "PUT" }-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertContentType "application/json" resp-      T.assertBody "[1,2,3]" resp-      T.assertHeader "Cache-Control" "foo" resp--  , Hu.testCase "Proper OPTIONS response" $ runTest $ do-      let req = Wai.defaultRequest-                { Wai.requestMethod = "OPTIONS" }-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertBody "" resp-      T.assertHeader "Allow" "GET,HEAD,OPTIONS,PUT" resp--  , Hu.testCase "Proper HEAD response" $ runTest $ do-      let req = Wai.defaultRequest-                { Wai.requestMethod = "HEAD" }-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertBody "" resp-      T.assertHeader "Cache-Control" "foo" resp--  , Hu.testCase "Missing response at bad path" $ runTest $ do-      let req =-            Wai.defaultRequest-            & flip T.setPath "/hello"-      resp <- T.request req-      T.assertStatus 404 resp-      T.assertBody "" resp-      T.assertNoHeader "Cache-Control" resp--  , testGroup "Missing responses at wrong methods"-    $ flip map ["DELETE", "POST"] $ \method ->-      Hu.testCase ("Missing response at method " ++ method) $ runTest $ do-        let req =-              Wai.defaultRequest-              { Wai.requestMethod = fromString method }-        resp <- T.request req-        T.assertStatus 405 resp-        T.assertBody "" resp-        T.assertNoHeader "Cache-Control" resp-  ]--tests :: TestTree-tests = testGroup "Example 1" [ test1 ]
− test/Examples/Ex2.hs
@@ -1,91 +0,0 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeOperators     #-}---- | Here we test that a CORS response is properly handled. We assume that--- example.com is an acceptable Origin and that authorization IS allowed.-module Examples.Ex2 where--import           Data.Function       ((&))-import           Data.Proxy-import           Data.Text           (Text)-import qualified Network.Wai         as Wai-import qualified Network.Wai.Test    as T-import qualified Serv.Api            as A-import           Serv.Common-import qualified Serv.ContentType    as Ct-import qualified Serv.Cors           as Cors-import qualified Serv.Header         as H-import qualified Serv.Header.Proxies as Hp-import           Serv.Server-import           Test.Tasty-import qualified Test.Tasty.HUnit    as Hu--type RawBody = 'A.Body '[ Ct.TextPlain ] Text--type Api-  = 'A.Cors Cors.PermitAll 'A.:>-    'A.Header 'H.IfRange (Maybe RawText) 'A.:> 'A.Endpoint-    '[ 'A.Method 'A.GET '[ 'H.XCsrfToken 'A.::: RawText ] RawBody-     , 'A.Method 'A.DELETE '[] 'A.Empty-     ]--apiProxy :: Proxy Api-apiProxy = Proxy--impl :: Impl Api IO-impl _ifRange = get :<|> delete :<|> noOp-  where-    get =-      return-      $ emptyResponse ok200-      & withHeader Hp.xCsrfToken "some-csrf-token"-      & withBody "Hello"-    delete =-      return-      $ emptyResponse noContent204---server :: Server IO-server = handle apiProxy impl--config :: Config-config =-  defaultConfig--runTest :: T.Session a -> IO a-runTest = flip T.runSession (makeApplication config server)--test1 :: TestTree-test1 = testGroup "Simple responses"-  [ Hu.testCase "CORS successful GET response" $ runTest $ do-      let req = Wai.defaultRequest-                { Wai.requestHeaders = [("Origin", "http://example.com")] }-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertContentType "text/plain" resp-      T.assertBody "Hello" resp-      T.assertHeader "X-Csrf-Token" "some-csrf-token" resp-      T.assertHeader "Access-Control-Allow-Origin" "http://example.com" resp-      T.assertHeader "Access-Control-Expose-Headers" "X-Csrf-Token" resp-      T.assertHeader "Access-Control-Allow-Credentials" "true" resp-      T.assertHeader "Access-Control-Allow-Headers" "If-Range" resp-      T.assertNoHeader "Access-Control-Allow-Methods" resp--  , Hu.testCase "CORS successful OPTIONS pre-flight response" $ runTest $ do-      let req = Wai.defaultRequest-                { Wai.requestHeaders = [("Origin", "http://example.com")]-                , Wai.requestMethod = "OPTIONS"-                }-      resp <- T.request req-      T.assertStatus 200 resp-      T.assertBody "" resp-      T.assertHeader "Access-Control-Allow-Origin" "http://example.com" resp-      T.assertHeader "Access-Control-Allow-Methods" "DELETE,GET,HEAD,OPTIONS" resp-      T.assertHeader "Access-Control-Expose-Headers" "X-Csrf-Token" resp-      T.assertHeader "Access-Control-Allow-Credentials" "true" resp-      T.assertHeader "Access-Control-Allow-Headers" "If-Range" resp-  ]--tests :: TestTree-tests = testGroup "Example 2 -- CORS" [ test1 ]
− test/Spec.hs
@@ -1,33 +0,0 @@--import           Test.Tasty-import qualified Test.Tasty.HUnit             as Hu-import           Test.Tasty.Ingredients.Basic (consoleTestReporter,-                                               listingTests)-import           Test.Tasty.Runners.AntXML    (antXMLRunner)-import           Test.HUnit-import qualified Examples.Ex1 as Ex1-import qualified Examples.Ex2 as Ex2--main :: IO ()-main =-  defaultMainWithIngredients-  [ antXMLRunner-  , listingTests-  , consoleTestReporter-  ] tests--tests :: TestTree-tests =-  testGroup "Server Tests"-  [ systemTests-  , Ex1.tests-  , Ex2.tests-  ]--systemTests :: TestTree-systemTests = testGroup "System Tests"-  [ Hu.testCase "Trivial tests" trivial-  ] where--trivial :: Assertion-trivial = assertBool "True is False" True