]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
ImplantFile.hs now compiles.
authorPHO <pho@cielonegro.org>
Thu, 13 Oct 2011 12:38:25 +0000 (21:38 +0900)
committerPHO <pho@cielonegro.org>
Thu, 13 Oct 2011 12:38:25 +0000 (21:38 +0900)
Ditz-issue: 8959dadc07db1bd363283dee401073f6e48dc7fa

ImplantFile.hs
Lucu.cabal
Network/HTTP/Lucu/ETag.hs
Network/HTTP/Lucu/Resource.hs

index b95c45508cd23d11a134451081edd61c4de45a42..0e91f1c6bdbb7bd2b5667d68790325ad5ad88a95 100644 (file)
@@ -1,16 +1,17 @@
 {-# LANGUAGE
 {-# LANGUAGE
-    UnicodeSyntax
+    OverloadedStrings
+  , UnicodeSyntax
   #-}
 module Main where
 import Codec.Compression.GZip
 import Control.Applicative
 import Control.Monad
 import qualified Data.Ascii as A
   #-}
 module Main where
 import Codec.Compression.GZip
 import Control.Applicative
 import Control.Monad
 import qualified Data.Ascii as A
-import Data.Bits
 import qualified Data.ByteString.Base64 as B64
 import qualified Data.ByteString.Char8 as Strict
 import qualified Data.ByteString.Lazy as Lazy
 import Data.Char
 import qualified Data.ByteString.Base64 as B64
 import qualified Data.ByteString.Char8 as Strict
 import qualified Data.ByteString.Lazy as Lazy
 import Data.Char
+import Data.Digest.Pure.SHA
 import Data.Int
 import Data.Maybe
 import Data.Time
 import Data.Int
 import Data.Maybe
 import Data.Time
@@ -99,7 +100,7 @@ main = do (opts, sources, errors) ← getOpt Permute options <$> getArgs
                     exitWith $ ExitFailure 1
 
           when (length sources ≥ 2)
                     exitWith $ ExitFailure 1
 
           when (length sources ≥ 2)
-               $ error "too many input files."
+               $ fail "too many input files."
 
           generateHaskellSource opts (head sources)
 
 
           generateHaskellSource opts (head sources)
 
@@ -123,9 +124,9 @@ generateHaskellSource opts srcFile
 
          header ← mkHeader srcFile originalLen gzippedLen useGZip mimeType eTag lastMod
 
 
          header ← mkHeader srcFile originalLen gzippedLen useGZip mimeType eTag lastMod
 
-         let hsModule = mkModule (ModuleName modName) (name symName) imports decls
+         let hsModule = mkModule modName symName imports decls
              imports  = mkImports useGZip
              imports  = mkImports useGZip
-             decls    = concat [ declResourceDef
+             decls    = concat [ resourceDecl symName useGZip
                                , entityTagDecl eTag
                                , lastModifiedDecl lastMod
                                , contentTypeDecl mimeType
                                , entityTagDecl eTag
                                , lastModifiedDecl lastMod
                                , contentTypeDecl mimeType
@@ -134,103 +135,53 @@ generateHaskellSource opts srcFile
                                  else
                                      dataDecl (name "rawData") rawB64
                                ]
                                  else
                                      dataDecl (name "rawData") rawB64
                                ]
-             declResourceDef
-                 = [ HsTypeSig (⊥) [HsIdent symName]
-                               (HsQualType []
-                                (HsTyCon (UnQual (HsIdent "ResourceDef"))))
-                   , HsFunBind [HsMatch (⊥) (HsIdent symName)
-                                [] (HsUnGuardedRhs defResourceDef) []]
-                   ]
-
-             defResourceDef ∷ HsExp
-             defResourceDef 
-                 = let defResGet = if useGZip
-                                   then defResGetGZipped
-                                   else resGetRaw
-                   in 
-                     (HsRecConstr (UnQual (HsIdent "ResourceDef"))
-                      [ HsFieldUpdate (UnQual (HsIdent "resUsesNativeThread"))
-                                      (HsCon (UnQual (HsIdent "False")))
-                      , HsFieldUpdate (UnQual (HsIdent "resIsGreedy"))
-                                      (HsCon (UnQual (HsIdent "False")))
-                      , HsFieldUpdate (UnQual (HsIdent "resGet")) defResGet
-                      , HsFieldUpdate (UnQual (HsIdent "resHead"))
-                                      (HsCon (UnQual (HsIdent "Nothing")))
-                      , HsFieldUpdate (UnQual (HsIdent "resPost"))
-                                      (HsCon (UnQual (HsIdent "Nothing")))
-                      , HsFieldUpdate (UnQual (HsIdent "resPut"))
-                                      (HsCon (UnQual (HsIdent "Nothing")))
-                      , HsFieldUpdate (UnQual (HsIdent "resDelete"))
-                                      (HsCon (UnQual (HsIdent "Nothing")))
-                      ]
-                     )
-
-             defResGetGZipped ∷ HsExp
-             defResGetGZipped
-                 = let doExp = HsDo [ foundEntityStmt
-                                    , setContentTypeStmt
-                                    , bindMustGunzip
-                                    , doConditionalOutput
-                                    ]
-                       bindMustGunzip
-                           = HsGenerator (⊥)
-                             (HsPVar (HsIdent "mustGunzip"))
-                             (HsApp (HsApp (HsVar (UnQual (HsIdent "liftM")))
-                                     (HsVar (UnQual (HsIdent "not"))))
-                              (HsParen
-                               (HsApp (HsVar (UnQual (HsIdent "isEncodingAcceptable")))
-                                      (HsLit (HsString "gzip")))))
-                       doConditionalOutput
-                           = HsQualifier
-                             (HsIf (HsVar (UnQual (HsIdent "mustGunzip")))
-                                   expOutputGunzipped
-                                   expOutputGZipped)
-                       expOutputGunzipped
-                           = (HsApp (HsVar (UnQual (HsIdent "outputLBS")))
-                              (HsParen
-                               (HsApp (HsVar (UnQual (HsIdent "decompress")))
-                                      (HsVar (UnQual (HsIdent "gzippedData"))))))
-                       expOutputGZipped
-                           = HsDo [ setContentEncodingGZipStmt
-                                  , outputStmt (var $ name "gzippedData")
-                                  ]
-                   in 
-                     HsApp (HsCon (UnQual (HsIdent "Just")))
-                           (HsParen doExp)
 
          hPutStrLn output header
          hPutStrLn output (prettyPrint hsModule)
          hClose output
 
 
          hPutStrLn output header
          hPutStrLn output (prettyPrint hsModule)
          hClose output
 
-mkModule ∷ ModuleName → Name → [ImportDecl] → [Decl]
+mkModule ∷ ModuleName → Name → [ImportDecl] → [Decl] → Module
 mkModule modName symName imports decls
 mkModule modName symName imports decls
-    = let modPragma = [ LanguagePragma (⊥) [ name (show OverloadedStrings)
-                                           ]
-                      ]
-          exports   = [ EVar (UnQual symName)
-                      ]
+    = let modPragma = [ LanguagePragma (⊥) [ name (show OverloadedStrings) ] ]
+          exports   = [ EVar (UnQual symName) ]
       in
         Module (⊥) modName modPragma Nothing (Just exports) imports decls
 
 mkImports ∷ Bool → [ImportDecl]
 mkImports useGZip
     = [ ImportDecl (⊥) (ModuleName "Data.ByteString.Base64")
       in
         Module (⊥) modName modPragma Nothing (Just exports) imports decls
 
 mkImports ∷ Bool → [ImportDecl]
 mkImports useGZip
     = [ ImportDecl (⊥) (ModuleName "Data.ByteString.Base64")
-                   True False (Just (ModuleName "B64")) Nothing
+                   True False Nothing (Just (ModuleName "B64")) Nothing
       , ImportDecl (⊥) (ModuleName "Data.ByteString.Lazy")
       , ImportDecl (⊥) (ModuleName "Data.ByteString.Lazy")
-                   True False (Just (ModuleName "Lazy")) Nothing
+                   True False Nothing (Just (ModuleName "Lazy")) Nothing
       , ImportDecl (⊥) (ModuleName "Data.Time")
       , ImportDecl (⊥) (ModuleName "Data.Time")
-                   False False Nothing Nothing
+                   False False Nothing Nothing Nothing
       , ImportDecl (⊥) (ModuleName "Network.HTTP.Lucu")
       , ImportDecl (⊥) (ModuleName "Network.HTTP.Lucu")
-                   False False Nothing Nothing
+                   False False Nothing Nothing Nothing
       ]
       ⧺
       if useGZip then
           [ ImportDecl (⊥) (ModuleName "Codec.Compression.GZip")
       ]
       ⧺
       if useGZip then
           [ ImportDecl (⊥) (ModuleName "Codec.Compression.GZip")
-                       False False Nothing Nothing
+                       False False Nothing Nothing Nothing
           ]
       else
           []
 
           ]
       else
           []
 
+resourceDecl ∷ Name → Bool → [Decl]
+resourceDecl symName useGZip
+    = [ TypeSig (⊥) [symName] (TyCon (UnQual (name "ResourceDef")))
+      , nameBind (⊥) symName valExp
+      ]
+    where
+      valExp ∷ Exp
+      valExp = RecUpdate (var $ name "emptyResource")
+               [ FieldUpdate (UnQual (name "resGet" )) resGet
+               , FieldUpdate (UnQual (name "resHead")) resHead
+               ]
+
+      resGet ∷ Exp
+      resGet | useGZip   = resGetGZipped
+             | otherwise = resGetRaw
+
 resHead ∷ Exp
 resHead
     = infixApp (var $ name "Just")
 resHead ∷ Exp
 resHead
     = infixApp (var $ name "Just")
@@ -239,6 +190,38 @@ resHead
                     , setContentTypeStmt
                     ])
 
                     , setContentTypeStmt
                     ])
 
+resGetGZipped ∷ Exp
+resGetGZipped
+    = infixApp (var $ name "Just")
+               (op  $ name "$"   )
+               (doE [ foundEntityStmt
+                    , setContentTypeStmt
+                    , bindGZipStmt
+                    , conditionalOutputStmt
+                    ])
+    where
+      condVarName ∷ Name
+      condVarName = name "gzipAllowed"
+
+      dataVarName ∷ Name
+      dataVarName = name "gzippedData"
+
+      bindGZipStmt ∷ Stmt
+      bindGZipStmt
+          = genStmt (⊥)
+            (pvar condVarName)
+            (metaFunction "isEncodingAcceptable" [strE "gzip"])
+
+      conditionalOutputStmt ∷ Stmt
+      conditionalOutputStmt
+          = qualStmt $
+            If (var condVarName)
+               (doE [ setContentEncodingGZipStmt
+                    , outputStmt (var dataVarName)
+                    ])
+               (metaFunction "output"
+                [paren (metaFunction "decompress" [var dataVarName])])
+
 resGetRaw ∷ Exp
 resGetRaw
     = infixApp (var $ name "Just")
 resGetRaw ∷ Exp
 resGetRaw
     = infixApp (var $ name "Just")
@@ -285,9 +268,6 @@ entityTagDecl eTag
       valExp ∷ Exp
       valExp = metaFunction "parseETag" [strE $ eTagToString eTag]
 
       valExp ∷ Exp
       valExp = metaFunction "parseETag" [strE $ eTagToString eTag]
 
-      eTagToString ∷ ETag → String
-      eTagToString = A.toString ∘ A.fromAsciiBuilder ∘ printETag
-
 lastModifiedDecl ∷ UTCTime → [Decl]
 lastModifiedDecl lastMod
     = [ TypeSig (⊥) [varName] (TyCon (UnQual (name "UTCTime")))
 lastModifiedDecl ∷ UTCTime → [Decl]
 lastModifiedDecl lastMod
     = [ TypeSig (⊥) [varName] (TyCon (UnQual (name "UTCTime")))
@@ -310,7 +290,7 @@ contentTypeDecl mime
       varName = name "contentType"
 
       valExp ∷ Exp
       varName = name "contentType"
 
       valExp ∷ Exp
-      valExp = metaFunction "parseMIMEType" [mimeToString mime]
+      valExp = metaFunction "parseMIMEType" [strE $ mimeToString mime]
 
       mimeToString ∷ MIMEType → String
       mimeToString = A.toString ∘ A.fromAsciiBuilder ∘ printMIMEType
 
       mimeToString ∷ MIMEType → String
       mimeToString = A.toString ∘ A.fromAsciiBuilder ∘ printMIMEType
@@ -332,64 +312,77 @@ dataDecl varName chunks
             `app`
             strE (Strict.unpack chunk)
 
             `app`
             strE (Strict.unpack chunk)
 
-mkHeader ∷ FilePath → Int64 → Int64 → Bool → MIMEType → String → UTCTime → IO String
+mkHeader ∷ FilePath → Int64 → Int64 → Bool → MIMEType → ETag → UTCTime → IO String
 mkHeader srcFile originalLen gzippedLen useGZip mimeType eTag lastMod
     = do localLastMod ← utcToLocalZonedTime lastMod
 mkHeader srcFile originalLen gzippedLen useGZip mimeType eTag lastMod
     = do localLastMod ← utcToLocalZonedTime lastMod
-         return ("{- DO NOT EDIT THIS FILE.\n" ++
-                 "   This file is automatically generated by the lucu-implant-file program.\n" ++
-                 "\n" ++
-                 "              Source: " ++ (if srcFile ≡ "-"
-                                              then "(stdin)"
-                                              else srcFile) ++ "\n" ++
-                 "     Original Length: " ++ show originalLen ++ " bytes\n" ++
-                 (if useGZip
-                  then "   Compressed Length: " ++ show gzippedLen ++ " bytes\n" ++
-                       "         Compression: gzip\n"
-                  else "         Compression: disabled\n") ++
-                 "           MIME Type: " ++ show mimeType ++ "\n" ++
-                 "                ETag: " ++ eTag ++ "\n" ++
-                 "       Last Modified: " ++ show localLastMod ++ "\n" ++
-                 " -}")
-
-
-getModuleName ∷ [CmdOpt] → IO String
+         return $ concat
+                    [ "{- DO NOT EDIT THIS FILE.\n"
+                    , "   This file is automatically generated by the lucu-implant-file program.\n"
+                    , "\n"
+                    , "              Source: ", if srcFile ≡ "-" then
+                                                    "(stdin)"
+                                                else
+                                                    srcFile
+                    , "\n"
+                    , "     Original Length: ", show originalLen, " bytes\n"
+                    , if useGZip then
+                          "   Compressed Length: " ⧺ show gzippedLen ⧺ " bytes\n" ⧺
+                          "         Compression: gzip\n"
+                      else
+                          "         Compression: disabled\n"
+                    , "           MIME Type: ", show mimeType, "\n"
+                    , "                ETag: ", eTagToString eTag, "\n"
+                    , "       Last Modified: ", show localLastMod, "\n"
+                    , " -}"
+                    ]
+
+eTagToString ∷ ETag → String
+eTagToString = A.toString ∘ A.fromAsciiBuilder ∘ printETag
+
+getModuleName ∷ [CmdOpt] → IO ModuleName
 getModuleName opts
 getModuleName opts
-    = let modNameOpts = filter (\ x → case x of
-                                         OptModName _ → True
-                                         _            → False) opts
-      in
-        case modNameOpts of
-          []                      → error "a module name must be given."
-          (OptModName modName):[] → return modName
-          _                       → error "too many --module options."
-
-
-getSymbolName ∷ [CmdOpt] → String → IO String
-getSymbolName opts modName
-    = let symNameOpts    = filter (\ x → case x of
-                                            OptSymName _ → True
-                                            _            → False) opts
-          -- モジュール名をピリオドで分割した時の最後の項目の先頭文字を
-          -- 小文字にしたものを使ふ。
-          defaultSymName  = mkDefault modName
-          mkDefault       = headToLower ∘ getLastComp
-          headToLower str = case str of
-                              []     → error "module name must not be empty"
-                              (x:xs) → toLower x : xs
-          getLastComp     = reverse ∘ fst ∘ break (≡ '.') ∘ reverse
-      in
-        case symNameOpts of
-          []                      → return defaultSymName
-          (OptSymName symName):[] → return symName
-          _                       → error "too many --symbol options."
+    = case modNameOpts of
+        []                      → fail "a module name must be given."
+        (OptModName modName):[] → return $ ModuleName modName
+        _                       → fail "too many --module options."
+    where
+      modNameOpts ∷ [CmdOpt]
+      modNameOpts = filter (\ x → case x of
+                                     OptModName _ → True
+                                     _            → False) opts
+
+getSymbolName ∷ [CmdOpt] → ModuleName → IO Name
+getSymbolName opts (ModuleName modName)
+    = case symNameOpts of
+        []                      → return defaultSymName
+        (OptSymName symName):[] → return $ name symName
+        _                       → fail "too many --symbol options."
+    where
+      symNameOpts ∷ [CmdOpt]
+      symNameOpts = filter (\ x → case x of
+                                     OptSymName _ → True
+                                     _            → False) opts
+
+      defaultSymName ∷ Name
+      defaultSymName
+          = name $ headToLower $ getLastComp modName
 
 
+      headToLower ∷ String → String
+      headToLower []     = error "module name must not be empty"
+      headToLower (x:xs) = toLower x : xs
+
+      getLastComp ∷ String → String
+      getLastComp = reverse ∘ fst ∘ break (≡ '.') ∘ reverse
 
 getMIMEType ∷ [CmdOpt] → FilePath → IO MIMEType
 getMIMEType opts srcFile
     = case mimeTypeOpts of
 
 getMIMEType ∷ [CmdOpt] → FilePath → IO MIMEType
 getMIMEType opts srcFile
     = case mimeTypeOpts of
-        []                  → return defaultType
-        (OptMIMEType ty):[] → return $ read ty
-        _                   → error "too many --mime-type options."
+        []  → return defaultType
+        (OptMIMEType ty):[]
+            → case A.fromChars ty of
+                 Just a  → return $ parseMIMEType a
+                 Nothing → fail "MIME type must not contain any non-ASCII letters."
+        _   → fail "too many --mime-type options."
     where
       mimeTypeOpts ∷ [CmdOpt]
       mimeTypeOpts
     where
       mimeTypeOpts ∷ [CmdOpt]
       mimeTypeOpts
@@ -404,59 +397,49 @@ getMIMEType opts srcFile
       defaultType = fromMaybe octetStream
                     $ guessTypeByFileName defaultExtensionMap srcFile
 
       defaultType = fromMaybe octetStream
                     $ guessTypeByFileName defaultExtensionMap srcFile
 
-
 getLastModified ∷ FilePath → IO UTCTime
 getLastModified "-"   = getCurrentTime
 getLastModified fpath = (posixSecondsToUTCTime ∘ fromRational ∘ toRational ∘ modificationTime)
                         <$>
                         getFileStatus fpath
 
 getLastModified ∷ FilePath → IO UTCTime
 getLastModified "-"   = getCurrentTime
 getLastModified fpath = (posixSecondsToUTCTime ∘ fromRational ∘ toRational ∘ modificationTime)
                         <$>
                         getFileStatus fpath
 
-
-getETag ∷ [CmdOpt] → Lazy.ByteString → IO String
+getETag ∷ [CmdOpt] → Lazy.ByteString → IO ETag
 getETag opts input
 getETag opts input
-    = let eTagOpts = filter (\ x → case x of
-                                      OptETag _ → True
-                                      _         → False) opts
-      in
-        case eTagOpts of
-          []               → fmap (mkETagFromInput ∘ fromJust) (getDigestByName "SHA1")
-          (OptETag str):[] → return str
-          _                → error "too many --etag options."
+    = case eTagOpts of
+        []               → return $ mkETagFromInput
+        (OptETag str):[] → return $ strToETag str
+        _                → fail "too many --etag options."
     where
     where
-      mkETagFromInput ∷ Digest → String
-      mkETagFromInput sha1 = "SHA-1:" ++ toHex (digestLBS sha1 input)
-
-      toHex ∷ String → String
-      toHex = foldr ((++) ∘ hexByte ∘ fromEnum) ""
-
-      hexByte ∷ Int → String
-      hexByte n
-          = [ hex4bit ((n `shiftR` 4) .&. 0x0F)
-            , hex4bit ( n             .&. 0x0F)
-            ]
+      eTagOpts ∷ [CmdOpt]
+      eTagOpts = filter (\ x → case x of
+                                  OptETag _ → True
+                                  _         → False) opts
 
 
-      hex4bit ∷ Int → Char
-      hex4bit n
-          | n < 10    = chr $ ord '0' + n
-          | n < 16    = chr $ ord 'a' + n - 10
-          | otherwise = (⊥)
+      mkETagFromInput ∷ ETag
+      mkETagFromInput
+          = strToETag $ "SHA-1:" ⧺ showDigest (sha1 input)
 
 
+      strToETag ∷ String → ETag
+      strToETag str
+          = case A.fromChars str of
+              Just a  → strongETag a
+              Nothing → error "ETag must not contain any non-ASCII letters."
 
 openInput ∷ FilePath → IO Lazy.ByteString
 openInput "-"   = Lazy.getContents
 openInput fpath = Lazy.readFile fpath
 
 
 openInput ∷ FilePath → IO Lazy.ByteString
 openInput "-"   = Lazy.getContents
 openInput fpath = Lazy.readFile fpath
 
-
 openOutput ∷ [CmdOpt] → IO Handle
 openOutput opts
 openOutput ∷ [CmdOpt] → IO Handle
 openOutput opts
-    = let outputOpts = filter (\ x → case x of
-                                        OptOutput _ → True
-                                        _           → False) opts
-      in
-        case outputOpts of
-          []                   → return stdout
-          (OptOutput fpath):[] → openFile fpath WriteMode
-          _                    → error "two many --output options."
+    = case outputOpts of
+        []                   → return stdout
+        (OptOutput fpath):[] → openFile fpath WriteMode
+        _                    → fail "two many --output options."
+    where
+      outputOpts ∷ [CmdOpt]
+      outputOpts = filter (\ x → case x of
+                                    OptOutput _ → True
+                                    _           → False) opts
 
 {-
   作られるファイルの例 (壓縮されない場合):
 
 {-
   作られるファイルの例 (壓縮されない場合):
@@ -469,7 +452,7 @@ openOutput opts
      Compressed Length: 453 bytes  -- これは Compression: disabled の時には無い
            Compression: disabled
              MIME Type: image/png
      Compressed Length: 453 bytes  -- これは Compression: disabled の時には無い
            Compression: disabled
              MIME Type: image/png
-                  ETag: d41d8cd98f00b204e9800998ecf8427e
+                  ETag: "d41d8cd98f00b204e9800998ecf8427e"
          Last Modified: 2007-11-05 13:53:42.231882 JST
    -}
   {-# LANGUAGE OverloadedStrings #-}
          Last Modified: 2007-11-05 13:53:42.231882 JST
    -}
   {-# LANGUAGE OverloadedStrings #-}
@@ -525,8 +508,8 @@ openOutput opts
             = Just $ do foundEntity entityTag lastModified
                         setContentType contentType
 
             = Just $ do foundEntity entityTag lastModified
                         setContentType contentType
 
-                        gzip ← isEncodingAcceptable "gzip"
-                        if gzip then
+                        gzipAllowed ← isEncodingAcceptable "gzip"
+                        if gzipAllowed then
                             do setContentEncoding ["gzip"]
                                output gzippedData
                         else
                             do setContentEncoding ["gzip"]
                                output gzippedData
                         else
index 0667fe28a225aedb9d53a659d35017cfc8506010..93731338a7862b4de989ddd316c28462b22f49c2 100644 (file)
@@ -106,7 +106,6 @@ Library
 
     ghc-options:
         -Wall
 
     ghc-options:
         -Wall
-        -funbox-strict-fields
 
 Executable lucu-implant-file
     if flag(build-lucu-implant-file)
 
 Executable lucu-implant-file
     if flag(build-lucu-implant-file)
@@ -116,9 +115,11 @@ Executable lucu-implant-file
 
     Main-Is: ImplantFile.hs
 
 
     Main-Is: ImplantFile.hs
 
+    Build-Depends:
+        SHA == 1.5.*
+
     ghc-options:
         -Wall
     ghc-options:
         -Wall
-        -funbox-strict-fields
 
 --Executable HelloWorld
 --    Main-Is: HelloWorld.hs
 
 --Executable HelloWorld
 --    Main-Is: HelloWorld.hs
index 7e618782c45e17e75ec16ef8667510447c518a20..9bfa9aa29e67555499dc62bfecfa3b8b8f97b04b 100644 (file)
@@ -16,7 +16,7 @@ module Network.HTTP.Lucu.ETag
     where
 import Control.Applicative
 import Control.Monad
     where
 import Control.Applicative
 import Control.Monad
-import Data.Ascii (Ascii)
+import Data.Ascii (Ascii, AsciiBuilder)
 import qualified Data.Ascii as A
 import Data.Attoparsec.Char8
 import Data.Monoid.Unicode
 import qualified Data.Ascii as A
 import Data.Attoparsec.Char8
 import Data.Monoid.Unicode
@@ -34,17 +34,16 @@ data ETag = ETag {
     , etagToken  ∷ !Ascii
     } deriving (Eq, Show)
 
     , etagToken  ∷ !Ascii
     } deriving (Eq, Show)
 
--- |Convert an 'ETag' to 'Ascii'.
-printETag ∷ ETag → Ascii
+-- |Convert an 'ETag' to 'AsciiBuilder'.
+printETag ∷ ETag → AsciiBuilder
 printETag et
 printETag et
-    = A.fromAsciiBuilder $
-      ( ( if etagIsWeak et then
-              A.toAsciiBuilder "W/"
-          else
-              (∅)
-        )
-        ⊕
-        quoteStr (etagToken et) )
+    = ( if etagIsWeak et then
+            A.toAsciiBuilder "W/"
+        else
+            (∅)
+      )
+      ⊕
+      quoteStr (etagToken et)
 
 -- |Parse 'Etag' from an 'Ascii'. This functions throws an exception
 -- for parse error.
 
 -- |Parse 'Etag' from an 'Ascii'. This functions throws an exception
 -- for parse error.
index 01b61813971e9e1ce4ba80e18ed374e400a5ce5a..975744c5164f30ee6323fc1b48a222b710fc5da8 100644 (file)
@@ -456,7 +456,9 @@ foundETag tag
       
          method ← getMethod
          when (method ≡ GET ∨ method ≡ HEAD)
       
          method ← getMethod
          when (method ≡ GET ∨ method ≡ HEAD)
-              $ setHeader' "ETag" (printETag tag)
+              $ setHeader' "ETag"
+              $ A.fromAsciiBuilder
+              $ printETag tag
          when (method ≡ POST)
               $ abort InternalServerError []
                 (Just "Illegal computation of foundETag for POST request.")
          when (method ≡ POST)
               $ abort InternalServerError []
                 (Just "Illegal computation of foundETag for POST request.")