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
13 , module Language.Symantic.HTTP.URI
16 -- import qualified Data.ByteString.Lazy as BSL
17 import Control.Applicative (Applicative(..))
18 import Control.Monad ()
20 import Data.Either (Either(..))
21 import Data.Function (($))
22 import Data.Functor ((<$>), (<$))
23 import Data.Maybe (Maybe(..))
24 import Data.Proxy (Proxy(..))
25 import Data.Semigroup (Semigroup(..))
26 import Data.String (IsString(..))
28 import Prelude (error)
29 import Text.Show (Show(..))
30 import qualified Data.Text as Text
31 import qualified Data.Time as Time
32 import qualified Network.HTTP.Media as Media
33 import qualified Network.HTTP.Types as HTTP
34 import qualified Network.HTTP.Types.Header as HTTP
35 import qualified Network.Wai as Wai
36 import qualified Network.Wai.Handler.Warp as Warp
38 import Language.Symantic.HTTP.API
39 import Language.Symantic.HTTP.Media
40 import Language.Symantic.HTTP.Router
41 import Language.Symantic.HTTP.Layout
42 import Language.Symantic.HTTP.URI
47 | API0_Time Time.ZonedTime
50 instance IsString Time.TimeZone where
51 fromString s = case s of
52 "CEST" -> Time.TimeZone 2 True "CEST"
53 "CET" -> Time.TimeZone 1 False "CET"
54 _ -> error "unknown TimeZone"
57 api0 :: HTTP_API repr => repr ()
62 api00 :: HTTP_API repr => repr ()
68 api000 :: HTTP_API repr => repr ()
78 <*> capture "timezone"
79 <*> endpoint HTTP.methodGet plainText <+>
82 <*> endpoint HTTP.methodGet plainText
86 (\_tz (Proxy::Proxy ()) -> ())
87 (\(Proxy::Proxy ()) -> ())
90 cli1 :: Client Application
92 (\tz (CommandEndPoint respond) _req res -> do
93 time <- Time.utcToZonedTime (fromString $ Text.unpack tz) <$> Time.getCurrentTime
94 res $ Right $ respond (HTTP.mkStatus 200 "") [] $ show time <> "\n")
95 (\(CommandEndPoint respond) _req res -> do
96 date <- Time.utctDay <$> Time.getCurrentTime
97 res $ Right $ respond (HTTP.mkStatus 200 "") [] $ show date <> "\n")
100 rou1 :: Router Application
102 (\tz (RouterEndpoint respond) -> Application $ \_req res -> do
103 time <- Time.utcToZonedTime (fromString $ Text.unpack tz) <$> Time.getCurrentTime
104 res $ Right $ respond (HTTP.mkStatus 200 "") [] $ show time <> "\n")
105 (\(RouterEndpoint respond) -> Application $ \_req res -> do
106 date <- Time.utctDay <$> Time.getCurrentTime
107 res $ Right $ respond (HTTP.mkStatus 200 "") [] $ show date <> "\n")
110 srv1 = Warp.run 8080 $ runRouterApp rou1
112 api2 :: HTTP_API repr => repr Application
114 (\too respond _req res ->
115 res $ Right $ respond (HTTP.mkStatus 200 "") [] too)
118 <*> endpoint HTTP.methodGet plainText
120 api3 f = f <$ segment "me" <*> capture "too" <*> capture "too"
123 req1_1 :: Wai.Request
124 req1_1 = Wai.defaultRequest
125 { Wai.requestMethod = HTTP.methodGet
126 , Wai.pathInfo = ["date"]
127 , Wai.requestHeaders =
128 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
131 req1_2 :: Wai.Request
132 req1_2 = Wai.defaultRequest
133 { Wai.requestMethod = HTTP.methodGet
134 , Wai.pathInfo = ["time", "CEST"]
135 , Wai.requestHeaders =
136 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
139 req1_3 :: Wai.Request
140 req1_3 = Wai.defaultRequest
141 { Wai.requestMethod = HTTP.methodPost
142 , Wai.pathInfo = ["clock"]
144 [ ("reset", Just "1") ]
147 req1_KO_1 :: Wai.Request
148 req1_KO_1 = Wai.defaultRequest
149 { Wai.requestMethod = HTTP.methodPut
150 , Wai.pathInfo = ["time", "CEST"]
151 , Wai.requestHeaders =
152 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
155 req1_KO_2 :: Wai.Request
156 req1_KO_2 = Wai.defaultRequest
157 { Wai.requestMethod = HTTP.methodGet
158 , Wai.pathInfo = ["non-existent"]
159 , Wai.requestHeaders =
160 [ (HTTP.hAccept, Media.renderHeader $ mediaType plainText) ]
163 req1_KO_3 :: Wai.Request
164 req1_KO_3 = Wai.defaultRequest
165 { Wai.requestMethod = HTTP.methodGet
166 , Wai.pathInfo = ["date"]
167 , Wai.requestHeaders =
168 [ (HTTP.hAccept, "application/non-sense") ]
171 req1_KO_4 :: Wai.Request
172 req1_KO_4 = Wai.defaultRequest
173 { Wai.requestMethod = HTTP.methodGet
174 , Wai.pathInfo = ["date"]
175 , Wai.requestHeaders =
176 [ (HTTP.hHost, "example.com") ]
179 req1_KO_5 :: Wai.Request
180 req1_KO_5 = Wai.defaultRequest
181 { Wai.requestMethod = HTTP.methodPost
182 , Wai.pathInfo = ["clock"]
184 [ ("reset", Just "NaN") ]
191 [ req1_1, req1_2, req1_3
192 , req1_KO_1, req1_KO_2, req1_KO_3, req1_KO_4, req1_KO_5