6 module Network.HTTP.Lucu.ETag
17 import Control.Applicative
19 import Data.Ascii (Ascii, AsciiBuilder)
20 import qualified Data.Ascii as A
21 import Data.Attoparsec.Char8
22 import Data.Monoid.Unicode
23 import Network.HTTP.Lucu.Parser
24 import Network.HTTP.Lucu.Parser.Http hiding (token)
25 import Network.HTTP.Lucu.Utils
26 import Prelude.Unicode
28 -- |An entity tag consists of a weakness flag and an opaque string.
30 -- |The weakness flag. Weak tags looks like W\/\"blahblah\" and
31 -- strong tags are like \"blahblah\". See:
32 -- <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3>
34 -- |An opaque string. Only characters from 0x20 (sp) to 0x7e (~)
39 -- |Convert an 'ETag' to an 'AsciiBuilder'.
40 printETag ∷ ETag → AsciiBuilder
41 {-# INLINEABLE printETag #-}
43 = ( if etagIsWeak et then
49 quoteStr (etagToken et)
51 -- |Parse 'Etag' from an 'Ascii'. This functions throws an exception
53 parseETag ∷ Ascii → ETag
54 {-# INLINEABLE parseETag #-}
56 = case parseOnly (finishOff eTag) $ A.toByteString str of
58 Left err → error ("unparsable ETag: " ⧺ A.toString str ⧺ ": " ⧺ err)
60 -- |This is equivalent to @'ETag' 'False'@. If you want to generate an
61 -- ETag from a file, try using
62 -- 'Network.HTTP.Lucu.StaticFile.generateETagFromFile'.
63 strongETag ∷ Ascii → ETag
64 {-# INLINE strongETag #-}
65 strongETag = ETag False
67 -- |This is equivalent to @'ETag' 'True'@.
68 weakETag ∷ Ascii → ETag
69 {-# INLINE weakETag #-}
72 -- |'Parser' for an 'ETag'.
74 {-# INLINEABLE eTag #-}
75 eTag = do isWeak ← option False (string "W/" *> return True)
77 return $ ETag isWeak str
79 -- |'Parser' for a list of 'ETag's.
80 eTagList ∷ Parser [ETag]
81 {-# INLINEABLE eTagList #-}
82 eTagList = do xs ← listOf eTag
84 fail "empty list of ETags"