7 -- |Definition of things related on HTTP response.
8 module Network.HTTP.Lucu.Response
14 , module Network.HTTP.Lucu.StatusCode
33 import Data.Ascii (AsciiBuilder)
34 import qualified Data.Ascii as A
35 import Data.Monoid.Unicode
36 import Network.HTTP.Lucu.Headers
37 import Network.HTTP.Lucu.HttpVersion
38 import Network.HTTP.Lucu.StatusCode
39 import Network.HTTP.Lucu.StatusCode.Internal
40 import Prelude.Unicode
42 -- |Convert a 'StatusCode' to an 'AsciiBuilder'.
43 printStatusCode ∷ StatusCode sc ⇒ sc → AsciiBuilder
44 {-# INLINEABLE printStatusCode #-}
45 printStatusCode = A.toAsciiBuilder ∘ textualStatus
47 -- |This is the definition of an HTTP response.
48 data Response = Response {
49 resVersion ∷ !HttpVersion
50 , resStatus ∷ !SomeStatusCode
51 , resHeaders ∷ !Headers
54 instance HasHeaders Response where
55 getHeaders = resHeaders
56 setHeaders res hdr = res { resHeaders = hdr }
58 -- |Returns an HTTP\/1.1 'Response' with no header fields.
59 emptyResponse ∷ StatusCode sc ⇒ sc → Response
62 resVersion = HttpVersion 1 1
63 , resStatus = fromStatusCode sc
67 -- |@'setStatusCode' sc res@ sets the status code of @res@ to @sc@.
68 setStatusCode ∷ StatusCode sc ⇒ sc → Response → Response
71 resStatus = fromStatusCode sc
74 -- |Returns 'True' iff a given 'Response' allows the existence of
75 -- response entity body.
76 resCanHaveBody ∷ Response → Bool
77 {-# INLINEABLE resCanHaveBody #-}
78 resCanHaveBody (Response {..})
79 | isInformational resStatus = False
80 | resStatus ≈ NoContent = False
81 | resStatus ≈ ResetContent = False
82 | resStatus ≈ NotModified = False
85 -- |Convert a 'Response' to 'AsciiBuilder'.
86 printResponse ∷ Response → AsciiBuilder
87 {-# INLINEABLE printResponse #-}
88 printResponse (Response {..})
89 = printHttpVersion resVersion ⊕
90 A.toAsciiBuilder " " ⊕
91 printStatusCode resStatus ⊕
92 A.toAsciiBuilder "\x0D\x0A" ⊕
93 printHeaders resHeaders
95 -- |@'isInformational' sc@ returns 'True' iff @sc '<' 200@.
96 isInformational ∷ StatusCode sc ⇒ sc → Bool
97 {-# INLINE isInformational #-}
98 isInformational = satisfy (< 200)
100 -- |@'isSuccessful' sc@ returns 'True' iff @200 '<=' sc '<' 300@.
101 isSuccessful ∷ StatusCode sc ⇒ sc → Bool
102 {-# INLINE isSuccessful #-}
103 isSuccessful = satisfy (\ n → n ≥ 200 ∧ n < 300)
105 -- |@'isRedirection' sc@ returns 'True' iff @300 '<=' sc '<' 400@.
106 isRedirection ∷ StatusCode sc ⇒ sc → Bool
107 {-# INLINE isRedirection #-}
108 isRedirection = satisfy (\ n → n ≥ 300 ∧ n < 400)
110 -- |@'isError' sc@ returns 'True' iff @400 '<=' sc@
111 isError ∷ StatusCode sc ⇒ sc → Bool
112 {-# INLINE isError #-}
113 isError = satisfy (≥ 400)
115 -- |@'isClientError' sc@ returns 'True' iff @400 '<=' sc '<' 500@.
116 isClientError ∷ StatusCode sc ⇒ sc → Bool
117 {-# INLINE isClientError #-}
118 isClientError = satisfy (\ n → n ≥ 400 ∧ n < 500)
120 -- |@'isServerError' sc@ returns 'True' iff @500 '<=' sc@.
121 isServerError ∷ StatusCode sc ⇒ sc → Bool
122 {-# INLINE isServerError #-}
123 isServerError = satisfy (≥ 500)
125 satisfy ∷ StatusCode sc ⇒ (Int → Bool) → sc → Bool
126 {-# INLINE satisfy #-}
127 satisfy p (numericCode → num) = p num