@@ -1,22 +1,28 @@
1+{-# LANGUAGE CPP #-}
12{-# LANGUAGE DataKinds #-}
23{-# LANGUAGE FlexibleContexts #-}
34{-# LANGUAGE FlexibleInstances #-}
4−{-# LANGUAGE OverlappingInstances #-}
55{-# LANGUAGE OverloadedStrings #-}
66{-# LANGUAGE PolyKinds #-}
77{-# LANGUAGE ScopedTypeVariables #-}
88{-# LANGUAGE TypeFamilies #-}
99{-# LANGUAGE TypeOperators #-}
10+#if !MIN_VERSION_base(4,8,0)
11+{-# LANGUAGE OverlappingInstances #-}
12+#endif
13+
1014module Servant.Server.Internal where
1115
16+#if !MIN_VERSION_base(4,8,0)
1217import Control.Applicative ((<$>))
18+import Data.Monoid (Monoid, mappend, mempty)
19+#endif
1320import Control.Monad.Trans.Either (EitherT, runEitherT)
1421import qualified Data.ByteString as B
1522import qualified Data.ByteString.Lazy as BL
1623import Data.IORef (newIORef, readIORef, writeIORef)
1724import Data.List (unfoldr)
1825import Data.Maybe (catMaybes, fromMaybe)
19−import Data.Monoid (Monoid, mappend, mempty)
2026import Data.String (fromString)
2127import Data.String.Conversions (cs, (<>))
2228import Data.Text (Text)
@@ -278,10 +284,13 @@ instance HasServer Delete where
278284-- If successfully returning a value, we use the type-level list, combined
279285-- with the request's @Accept@ header, to encode the value for you
280286-- (returning a status code of 200). If there was no @Accept@ header or it
281−-- was @*/*@, we return encode using the first @Content-Type@ type on the
287+-- was @*\/\*@, we return encode using the first @Content-Type@ type on the
282288-- list.
283−instance ( AllCTRender ctypes a
284− ) => HasServer (Get ctypes a) where
289+instance
290+#if MIN_VERSION_base(4,8,0)
291+ {-# OVERLAPPABLE #-}
292+#endif
293+ ( AllCTRender ctypes a ) => HasServer (Get ctypes a) where
285294
286295 type ServerT' (Get ctypes a) m = m a
287296
@@ -290,7 +299,7 @@ instance ( AllCTRender ctypes a
290299 e <- runEitherT action
291300 respond $ case e of
292301 Right output -> do
293− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
302+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
294303 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
295304 Nothing -> failWith UnsupportedMediaType
296305 Just (contentT, body) -> succeedWith $
@@ -302,8 +311,14 @@ instance ( AllCTRender ctypes a
302311 | otherwise = respond $ failWith NotFound
303312
304313-- '()' ==> 204 No Content
305−instance HasServer (Get ctypes ()) where
314+instance
315+#if MIN_VERSION_base(4,8,0)
316+ {-# OVERLAPPING #-}
317+#endif
318+ HasServer (Get ctypes ()) where
319+
306320 type ServerT' (Get ctypes ()) m = m ()
321+
307322 route Proxy action request respond
308323 | pathIsEmpty request && requestMethod request == methodGet = do
309324 e <- runEitherT action
@@ -316,14 +331,20 @@ instance HasServer (Get ctypes ()) where
316331 | otherwise = respond $ failWith NotFound
317332
318333-- Add response headers
319−instance ( AllCTRender ctypes v ) => HasServer (Get ctypes (Headers h v)) where
334+instance
335+#if MIN_VERSION_base(4,8,0)
336+ {-# OVERLAPPING #-}
337+#endif
338+ ( AllCTRender ctypes v ) => HasServer (Get ctypes (Headers h v)) where
339+
320340 type ServerT' (Get ctypes (Headers h v)) m = m (Headers h v)
341+
321342 route Proxy action request respond
322343 | pathIsEmpty request && requestMethod request == methodGet = do
323344 e <- runEitherT action
324345 respond $ case e of
325346 Right output -> do
326− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
347+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
327348 headers = getHeaders output
328349 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) (getResponse output) of
329350 Nothing -> failWith UnsupportedMediaType
@@ -378,9 +399,13 @@ instance (KnownSymbol sym, FromText a, HasServer sublayout)
378399-- If successfully returning a value, we use the type-level list, combined
379400-- with the request's @Accept@ header, to encode the value for you
380401-- (returning a status code of 201). If there was no @Accept@ header or it
381−-- was @*/*@, we return encode using the first @Content-Type@ type on the
402+-- was @*\/\*@, we return encode using the first @Content-Type@ type on the
382403-- list.
383−instance ( AllCTRender ctypes a
404+instance
405+#if MIN_VERSION_base(4,8,0)
406+ {-# OVERLAPPABLE #-}
407+#endif
408+ ( AllCTRender ctypes a
384409 ) => HasServer (Post ctypes a) where
385410
386411 type ServerT' (Post ctypes a) m = m a
@@ -390,7 +415,7 @@ instance ( AllCTRender ctypes a
390415 e <- runEitherT action
391416 respond $ case e of
392417 Right output -> do
393− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
418+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
394419 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
395420 Nothing -> failWith UnsupportedMediaType
396421 Just (contentT, body) -> succeedWith $
@@ -401,8 +426,14 @@ instance ( AllCTRender ctypes a
401426 respond $ failWith WrongMethod
402427 | otherwise = respond $ failWith NotFound
403428
404−instance HasServer (Post ctypes ()) where
429+instance
430+#if MIN_VERSION_base(4,8,0)
431+ {-# OVERLAPPING #-}
432+#endif
433+ HasServer (Post ctypes ()) where
434+
405435 type ServerT' (Post ctypes ()) m = m ()
436+
406437 route Proxy action request respond
407438 | pathIsEmpty request && requestMethod request == methodPost = do
408439 e <- runEitherT action
@@ -415,14 +446,20 @@ instance HasServer (Post ctypes ()) where
415446 | otherwise = respond $ failWith NotFound
416447
417448-- Add response headers
418−instance ( AllCTRender ctypes v ) => HasServer (Post ctypes (Headers h v)) where
449+instance
450+#if MIN_VERSION_base(4,8,0)
451+ {-# OVERLAPPING #-}
452+#endif
453+ ( AllCTRender ctypes v ) => HasServer (Post ctypes (Headers h v)) where
454+
419455 type ServerT' (Post ctypes (Headers h v)) m = m (Headers h v)
456+
420457 route Proxy action request respond
421458 | pathIsEmpty request && requestMethod request == methodPost = do
422459 e <- runEitherT action
423460 respond $ case e of
424461 Right output -> do
425− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
462+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
426463 headers = getHeaders output
427464 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) (getResponse output) of
428465 Nothing -> failWith UnsupportedMediaType
@@ -445,10 +482,13 @@ instance ( AllCTRender ctypes v ) => HasServer (Post ctypes (Headers h v)) where
445482-- If successfully returning a value, we use the type-level list, combined
446483-- with the request's @Accept@ header, to encode the value for you
447484-- (returning a status code of 200). If there was no @Accept@ header or it
448−-- was @*/*@, we return encode using the first @Content-Type@ type on the
485+-- was @*\/\*@, we return encode using the first @Content-Type@ type on the
449486-- list.
450−instance ( AllCTRender ctypes a
451− ) => HasServer (Put ctypes a) where
487+instance
488+#if MIN_VERSION_base(4,8,0)
489+ {-# OVERLAPPABLE #-}
490+#endif
491+ ( AllCTRender ctypes a) => HasServer (Put ctypes a) where
452492
453493 type ServerT' (Put ctypes a) m = m a
454494
@@ -457,7 +497,7 @@ instance ( AllCTRender ctypes a
457497 e <- runEitherT action
458498 respond $ case e of
459499 Right output -> do
460− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
500+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
461501 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
462502 Nothing -> failWith UnsupportedMediaType
463503 Just (contentT, body) -> succeedWith $
@@ -468,8 +508,14 @@ instance ( AllCTRender ctypes a
468508 respond $ failWith WrongMethod
469509 | otherwise = respond $ failWith NotFound
470510
471−instance HasServer (Put ctypes ()) where
511+instance
512+#if MIN_VERSION_base(4,8,0)
513+ {-# OVERLAPPING #-}
514+#endif
515+ HasServer (Put ctypes ()) where
516+
472517 type ServerT' (Put ctypes ()) m = m ()
518+
473519 route Proxy action request respond
474520 | pathIsEmpty request && requestMethod request == methodPut = do
475521 e <- runEitherT action
@@ -482,14 +528,20 @@ instance HasServer (Put ctypes ()) where
482528 | otherwise = respond $ failWith NotFound
483529
484530-- Add response headers
485−instance ( AllCTRender ctypes v ) => HasServer (Put ctypes (Headers h v)) where
531+instance
532+#if MIN_VERSION_base(4,8,0)
533+ {-# OVERLAPPING #-}
534+#endif
535+ ( AllCTRender ctypes v ) => HasServer (Put ctypes (Headers h v)) where
536+
486537 type ServerT' (Put ctypes (Headers h v)) m = m (Headers h v)
538+
487539 route Proxy action request respond
488540 | pathIsEmpty request && requestMethod request == methodPut = do
489541 e <- runEitherT action
490542 respond $ case e of
491543 Right output -> do
492− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
544+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
493545 headers = getHeaders output
494546 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) (getResponse output) of
495547 Nothing -> failWith UnsupportedMediaType
@@ -512,8 +564,12 @@ instance ( AllCTRender ctypes v ) => HasServer (Put ctypes (Headers h v)) where
512564-- If successfully returning a value, we just require that its type has
513565-- a 'ToJSON' instance and servant takes care of encoding it for you,
514566-- yielding status code 200 along the way.
515−instance ( AllCTRender ctypes a
516− ) => HasServer (Patch ctypes a) where
567+instance
568+#if MIN_VERSION_base(4,8,0)
569+ {-# OVERLAPPABLE #-}
570+#endif
571+ ( AllCTRender ctypes a) => HasServer (Patch ctypes a) where
572+
517573 type ServerT' (Patch ctypes a) m = m a
518574
519575 route Proxy action request respond
@@ -521,7 +577,7 @@ instance ( AllCTRender ctypes a
521577 e <- runEitherT action
522578 respond $ case e of
523579 Right output -> do
524− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
580+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
525581 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) output of
526582 Nothing -> failWith UnsupportedMediaType
527583 Just (contentT, body) -> succeedWith $
@@ -532,8 +588,14 @@ instance ( AllCTRender ctypes a
532588 respond $ failWith WrongMethod
533589 | otherwise = respond $ failWith NotFound
534590
535−instance HasServer (Patch ctypes ()) where
591+instance
592+#if MIN_VERSION_base(4,8,0)
593+ {-# OVERLAPPING #-}
594+#endif
595+ HasServer (Patch ctypes ()) where
596+
536597 type ServerT' (Patch ctypes ()) m = m ()
598+
537599 route Proxy action request respond
538600 | pathIsEmpty request && requestMethod request == methodPatch = do
539601 e <- runEitherT action
@@ -546,14 +608,20 @@ instance HasServer (Patch ctypes ()) where
546608 | otherwise = respond $ failWith NotFound
547609
548610-- Add response headers
549−instance ( AllCTRender ctypes v ) => HasServer (Patch ctypes (Headers h v)) where
611+instance
612+#if MIN_VERSION_base(4,8,0)
613+ {-# OVERLAPPING #-}
614+#endif
615+ ( AllCTRender ctypes v ) => HasServer (Patch ctypes (Headers h v)) where
616+
550617 type ServerT' (Patch ctypes (Headers h v)) m = m (Headers h v)
618+
551619 route Proxy action request respond
552620 | pathIsEmpty request && requestMethod request == methodPatch = do
553621 e <- runEitherT action
554622 respond $ case e of
555623 Right outpatch -> do
556− let accH = fromMaybe "*/*" $ lookup hAccept $ requestHeaders request
624+ let accH = fromMaybe ct_wildcard $ lookup hAccept $ requestHeaders request
557625 headers = getHeaders outpatch
558626 case handleAcceptH (Proxy :: Proxy ctypes) (AcceptHeader accH) (getResponse outpatch) of
559627 Nothing -> failWith UnsupportedMediaType
@@ -864,3 +932,6 @@ instance (KnownSymbol path, HasServer sublayout) => HasServer (path :> sublayout
864932 _ -> respond $ failWith NotFound
865933
866934 where proxyPath = Proxy :: Proxy path
935+
936+ct_wildcard :: B.ByteString
937+ct_wildcard = "*" <> "/" <> "*" -- Because CPP