1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE NoMonomorphismRestriction #-}
3 {-# LANGUAGE StrictData #-}
4 {-# LANGUAGE TypeApplications #-}
5 {-# LANGUAGE TypeFamilies #-}
6 {-# OPTIONS_GHC -fno-warn-orphans #-}
7 module Language.Symantic.HTTP
8 ( module Language.Symantic.HTTP
9 , module Language.Symantic.HTTP.API
10 , module Language.Symantic.HTTP.Layout
11 , module Language.Symantic.HTTP.Media
12 , module Language.Symantic.HTTP.Router
15 -- import qualified Data.ByteString.Lazy as BSL
16 import Control.Applicative (Applicative(..))
17 import Control.Monad ()
19 import Data.Either (Either(..))
20 import Data.Function (($))
21 import Data.Functor ((<$>), (<$))
22 import Data.Maybe (Maybe(..))
23 import Data.Proxy (Proxy(..))
24 import Data.Semigroup (Semigroup(..))
25 import Data.String (IsString(..))
27 import Prelude (error)
28 import Text.Show (Show(..))
29 import qualified Data.Text as Text
30 import qualified Data.Time as Time
31 import qualified Network.HTTP.Media as Media
32 import qualified Network.HTTP.Types as HTTP
33 import qualified Network.HTTP.Types.Header as HTTP
34 import qualified Network.Wai as Wai
35 import qualified Network.Wai.Handler.Warp as Warp
37 import Language.Symantic.HTTP.API
38 import Language.Symantic.HTTP.Media
39 import Language.Symantic.HTTP.Router
40 import Language.Symantic.HTTP.Layout
45 | API0_Time Time.ZonedTime
48 instance IsString Time.TimeZone where
49 fromString s = case s of
50 "CEST" -> Time.TimeZone 2 True "CEST"
51 "CET" -> Time.TimeZone 1 False "CET"
52 _ -> error "unknown TimeZone"
55 api0 :: HTTP_API repr => repr ()
60 api00 :: HTTP_API repr => repr ()
66 api000 :: HTTP_API repr => repr ()
76 <*> capture "timezone"
77 <*> endpoint HTTP.methodGet plainText <+>
80 <*> endpoint HTTP.methodGet plainText
84 (\_tz (Proxy::Proxy ()) -> ())
85 (\(Proxy::Proxy ()) -> ())
87 rou1 :: Router Application
89 (\tz (RouterEndpoint respond) _rq re -> do
90 time <- Time.utcToZonedTime (fromString $ Text.unpack tz) <$> Time.getCurrentTime
91 re $ Right $ respond (HTTP.mkStatus 200 "") [] $ show time <> "\n")
92 (\(RouterEndpoint respond) _rq re -> do
93 date <- Time.utctDay <$> Time.getCurrentTime
94 re $ Right $ respond (HTTP.mkStatus 200 "") [] $ show date <> "\n")
97 srv1 = Warp.run 8080 $ runRouterApp rou1
99 api2 :: HTTP_API repr => repr Application
101 (\too respond _rq re ->
102 re $ Right $ respond (HTTP.mkStatus 200 "") [] too)
105 <*> endpoint HTTP.methodGet plainText
107 api3 f = f <$ segment "me" <*> capture "too" <*> capture "too"
110 req1_1 :: Wai.Request
111 req1_1 = Wai.defaultRequest
112 { Wai.requestMethod = HTTP.methodGet
113 , Wai.pathInfo = ["date"]
114 , Wai.requestHeaders =
115 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
118 req1_2 :: Wai.Request
119 req1_2 = Wai.defaultRequest
120 { Wai.requestMethod = HTTP.methodGet
121 , Wai.pathInfo = ["time", "CEST"]
122 , Wai.requestHeaders =
123 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
126 req1_3 :: Wai.Request
127 req1_3 = Wai.defaultRequest
128 { Wai.requestMethod = HTTP.methodPost
129 , Wai.pathInfo = ["clock"]
131 [ ("reset", Just "1") ]
134 req1_KO_1 :: Wai.Request
135 req1_KO_1 = Wai.defaultRequest
136 { Wai.requestMethod = HTTP.methodPut
137 , Wai.pathInfo = ["time", "CEST"]
138 , Wai.requestHeaders =
139 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
142 req1_KO_2 :: Wai.Request
143 req1_KO_2 = Wai.defaultRequest
144 { Wai.requestMethod = HTTP.methodGet
145 , Wai.pathInfo = ["non-existent"]
146 , Wai.requestHeaders =
147 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
150 req1_KO_3 :: Wai.Request
151 req1_KO_3 = Wai.defaultRequest
152 { Wai.requestMethod = HTTP.methodGet
153 , Wai.pathInfo = ["date"]
154 , Wai.requestHeaders =
155 [ (HTTP.hAccept, "application/non-sense") ]
158 req1_KO_4 :: Wai.Request
159 req1_KO_4 = Wai.defaultRequest
160 { Wai.requestMethod = HTTP.methodGet
161 , Wai.pathInfo = ["date"]
162 , Wai.requestHeaders =
163 [ (HTTP.hHost, "example.com") ]
166 req1_KO_5 :: Wai.Request
167 req1_KO_5 = Wai.defaultRequest
168 { Wai.requestMethod = HTTP.methodPost
169 , Wai.pathInfo = ["clock"]
171 [ ("reset", Just "NaN") ]
178 [ req1_1, req1_2, req1_3
179 , req1_KO_1, req1_KO_2, req1_KO_3, req1_KO_4, req1_KO_5