]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
Don't use the unix package at all.
authorPHO <pho@cielonegro.org>
Sat, 12 Nov 2011 09:10:47 +0000 (18:10 +0900)
committerPHO <pho@cielonegro.org>
Sat, 12 Nov 2011 09:10:47 +0000 (18:10 +0900)
Ditz-issue: ce2851ba49c154838b48e56ecf4c01840e4c1b7c

Lucu.cabal
Network/HTTP/Lucu/Httpd.hs
Network/HTTP/Lucu/Implant.hs
Network/HTTP/Lucu/Resource.hs
Network/HTTP/Lucu/StaticFile.hs
Network/HTTP/Lucu/Utils.hs
bugs/issue-ce2851ba49c154838b48e56ecf4c01840e4c1b7c.yaml

index 604fc273ac86d871ecc508af650881bac7531a79..e254dbdf59daa200f90e8bec3a0602fd82e96275 100644 (file)
@@ -53,22 +53,22 @@ Library
         base-unicode-symbols       == 0.2.*,
         base64-bytestring          == 0.1.*,
         blaze-builder              == 0.3.*,
-        blaze-textual              == 0.2.*,
         bytestring                 == 0.9.*,
         containers                 == 0.4.*,
         containers-unicode-symbols == 0.3.*,
+        directory                  == 1.1.*,
         filepath                   == 1.2.*,
         hxt                        == 9.1.*,
         mtl                        == 2.0.*,
         network                    == 2.3.*,
+        old-time                   == 1.0.*,
         stm                        == 2.2.*,
         stringsearch               == 0.3.*,
         template-haskell           == 2.5.*,
         text                       == 0.11.*,
         time                       == 1.2.*,
         time-http                  == 0.2.*,
-        transformers               == 0.2.*,
-        unix                       == 2.4.*
+        transformers               == 0.2.*
 
     Exposed-Modules:
         Network.HTTP.Lucu
index 595403abd0364f1a2e70c79088d9138d38eeaf90..c8a21b7d256d8c0d7128205c18e747dd0b52246f 100644 (file)
@@ -20,16 +20,11 @@ import Network.HTTP.Lucu.RequestReader
 import Network.HTTP.Lucu.Resource.Tree
 import Network.HTTP.Lucu.ResponseWriter
 import Network.HTTP.Lucu.SocketLike as SL
-import System.Posix.Signals
 
 -- |This is the entry point of Lucu httpd. It listens to a socket and
 -- waits for clients. 'runHttpd' never stops by itself so the only way
 -- to stop it is to raise an exception in the thread running it.
 --
--- Note that 'runHttpd' automatically makes SIGPIPE be ignored by
--- calling @'installHandler' 'sigPIPE' 'Ignore' 'Nothing'@. This can
--- hardly cause a problem though.
---
 -- Example:
 --
 -- > {-# LANGUAGE OverloadedStrings #-}
@@ -51,8 +46,7 @@ import System.Posix.Signals
 runHttpd ∷ Config → ResTree → [FallbackHandler] → IO ()
 runHttpd cnf tree fbs
     = withSocketsDo $
-      do void $ installHandler sigPIPE Ignore Nothing
-         let launchers
+      do let launchers
                  = catMaybes
                    [ do scnf ← cnfSSLConfig    cnf
                         addr ← cnfServerV4Addr cnf
index f80ac99cfdbc768bcb0f931ed50f0058b1364129..90c83f2f151c6c7d3563697d1ef0b921d18d683f 100644 (file)
@@ -22,14 +22,13 @@ import qualified Data.ByteString.Lazy as L
 import Data.Digest.Pure.SHA
 import Data.Maybe
 import Data.Time
-import Data.Time.Clock.POSIX
 import Network.HTTP.Lucu.ETag
 import Network.HTTP.Lucu.MIMEType hiding (mimeType)
 import Network.HTTP.Lucu.MIMEType.DefaultExtensionMap
 import Network.HTTP.Lucu.MIMEType.Guess
 import Network.HTTP.Lucu.MIMEType.TH
+import Network.HTTP.Lucu.Utils
 import Prelude.Unicode
-import System.Posix.Files
 
 data Input
     = Input {
@@ -77,13 +76,7 @@ openInput fpath ctype etag
 
 lastModified ∷ FilePath → IO UTCTime
 lastModified "-"   = getCurrentTime
-lastModified fpath = ( posixSecondsToUTCTime
-                     ∘ fromRational
-                     ∘ toRational
-                     ∘ modificationTime
-                     )
-                     <$>
-                     getFileStatus fpath
+lastModified fpath = getLastModified fpath
 
 openInputFile ∷ FilePath → IO L.ByteString
 openInputFile "-"   = L.getContents
index 97b2cbe3cb491c4b64853fe6a60bfab0895ca171..d1420ba5e5ba8d11433b2f902a881aceb34fee19 100644 (file)
@@ -450,7 +450,7 @@ foundTimeStamp timeStamp
          when (method ≡ POST)
              $ abort
              $ mkAbortion' InternalServerError
-               "Illegal computation of foundTimeStamp for POST request."
+               "Illegal call of foundTimeStamp for POST request."
 
          let statusForIfModSince
                  = if method ≡ GET ∨ method ≡ HEAD then
@@ -458,7 +458,6 @@ foundTimeStamp timeStamp
                    else
                        fromStatusCode PreconditionFailed
 
-         -- If-Modified-Since があればそれを見る。
          ifModSince ← getHeader "If-Modified-Since"
          case ifModSince of
            Just str → case HTTP.fromAscii str of
@@ -467,11 +466,11 @@ foundTimeStamp timeStamp
                                $ abort
                                $ mkAbortion' statusForIfModSince
                                $ "The entity has not been modified since " ⊕ A.toText str
-                         Left _
-                             → return () -- 不正な時刻は無視
+                         Left e
+                             → abort $ mkAbortion' BadRequest
+                                     $ "Malformed If-Modified-Since: " ⊕ T.pack e
            Nothing  → return ()
 
-         -- If-Unmodified-Since があればそれを見る。
          ifUnmodSince ← getHeader "If-Unmodified-Since"
          case ifUnmodSince of
            Just str → case HTTP.fromAscii str of
@@ -480,8 +479,9 @@ foundTimeStamp timeStamp
                                $ abort
                                $ mkAbortion' PreconditionFailed
                                $ "The entity has not been modified since " ⊕ A.toText str
-                         Left _
-                             → return () -- 不正な時刻は無視
+                         Left e
+                             → abort $ mkAbortion' BadRequest
+                                     $ "Malformed If-Unmodified-Since: " ⊕ T.pack e
            Nothing  → return ()
 
          driftTo ReceivingBody
index ffda4cf8dbbbc0a6f0bb41b9536dfb30ec2d2d1c..39ff39c41ded5da08304e33b1f5cc97f9651bb5e 100644 (file)
@@ -8,35 +8,28 @@
 module Network.HTTP.Lucu.StaticFile
     ( staticFile
     , staticDir
-
-    , generateETagFromFile
     )
     where
-import qualified Blaze.ByteString.Builder.ByteString as BB
-import qualified Blaze.Text.Int as BT
 import Control.Monad
 import Control.Monad.Unicode
 import Control.Monad.Trans
-import qualified Data.Ascii as A
 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Lazy.Char8 as LBS
-import Data.Monoid.Unicode
 import Data.String
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as T
-import Data.Time.Clock.POSIX
 import Network.HTTP.Lucu.Abortion
 import Network.HTTP.Lucu.Config
-import Network.HTTP.Lucu.ETag
 import Network.HTTP.Lucu.MIMEType hiding (mimeType)
 import Network.HTTP.Lucu.MIMEType.Guess
 import Network.HTTP.Lucu.MIMEType.TH
 import Network.HTTP.Lucu.Resource
 import Network.HTTP.Lucu.Resource.Internal
 import Network.HTTP.Lucu.Response
+import Network.HTTP.Lucu.Utils
 import Prelude.Unicode
+import System.Directory
 import System.FilePath
-import System.Posix.Files
 
 -- | @'staticFile' fpath@ is a 'ResourceDef' which serves the file at
 -- @fpath@ on the filesystem.
@@ -52,27 +45,17 @@ octetStream = [mimeType| application/octet-stream |]
 
 handleStaticFile ∷ Bool → FilePath → Resource ()
 handleStaticFile sendContent path
-    = do exists ← liftIO $ fileExist path
+    = do exists ← liftIO $ doesFileExist path
          unless exists
              foundNoEntity'
 
-         readable ← liftIO $ fileAccess path True False False
-         unless readable
-             $ abort
-             $ mkAbortion Forbidden [] Nothing
-
-         stat ← liftIO $ getFileStatus path
-         when (isDirectory stat)
+         perms ← liftIO $ getPermissions path
+         unless (readable perms)
              $ abort
              $ mkAbortion Forbidden [] Nothing
 
-         -- FIXME: Forget about ETags of a static file.
-         tag  ← liftIO $ generateETagFromFile path
-         let lastMod = posixSecondsToUTCTime
-                       $ fromRational
-                       $ toRational
-                       $ modificationTime stat
-         foundEntity tag lastMod
+         lastMod ← liftIO $ getLastModified path
+         foundTimeStamp lastMod
 
          conf ← getConfig
          case guessTypeByFileName (cnfExtToMIMEType conf) path of
@@ -82,33 +65,6 @@ handleStaticFile sendContent path
          when sendContent
              $ liftIO (LBS.readFile path) ≫= putChunks
 
--- |@'generateETagFromFile' fpath@ generates a strong entity tag from
--- a file. The file doesn't necessarily have to be a regular file; it
--- may be a FIFO or a device file. The tag is made of inode ID, size
--- and modification time.
---
--- Note that the tag is not strictly strong because the file could be
--- modified twice at a second without changing inode ID or size, but
--- it's not really possible to generate a strictly strong ETag from a
--- file as we don't want to simply grab the entire file and use it as
--- an ETag. It is indeed possible to hash it with SHA-1 or MD5 to
--- increase strictness, but it's too inefficient if the file is really
--- large (say, 1 TiB).
-generateETagFromFile ∷ FilePath → IO ETag
-generateETagFromFile path
-    = do stat ← getFileStatus path
-         let inode   = fileID   stat
-             size    = fileSize stat
-             lastMod = fromEnum $ modificationTime stat
-             tag     = A.fromAsciiBuilder
-                       $ A.unsafeFromBuilder
-                       $ BT.integral inode
-                       ⊕ BB.fromByteString "-"
-                       ⊕ BT.integral size
-                       ⊕ BB.fromByteString "-"
-                       ⊕ BT.integral lastMod
-         return $ strongETag tag
-
 -- | @'staticDir' dir@ is a 'ResourceDef' which maps all files in
 -- @dir@ and its subdirectories on the filesystem to the
 -- 'Network.HTTP.Lucu.Resource.Tree.ResTree'.
index 18370fab68cc3aa673b1ef6a85bf11bd3a87eb25..c07c9c9cf94891bf82213f5c24edf293ef534f12 100644 (file)
@@ -11,6 +11,9 @@ module Network.HTTP.Lucu.Utils
     , parseWWWFormURLEncoded
     , splitPathInfo
     , trim
+
+    , getLastModified
+
     , liftByteString
     , liftLazyByteString
     , liftAscii
@@ -20,6 +23,7 @@ module Network.HTTP.Lucu.Utils
     , liftUTCTime
     )
     where
+import Control.Applicative
 import Control.Monad
 import Data.Ascii (Ascii, CIAscii, AsciiBuilder)
 import qualified Data.Ascii as A
@@ -35,11 +39,14 @@ import Data.Ratio
 import Data.Text (Text)
 import qualified Data.Text as T
 import Data.Time
+import Data.Time.Clock.POSIX
 import Language.Haskell.TH.Lib
 import Language.Haskell.TH.Syntax
 import Network.URI
 import Prelude hiding (last)
 import Prelude.Unicode
+import System.Directory
+import System.Time (ClockTime(..))
 
 -- |>>> splitBy (== ':') "ab:c:def"
 -- ["ab", "c", "def"]
@@ -111,6 +118,16 @@ trim = reverse ∘ f ∘ reverse ∘ f
     where
       f = dropWhile isSpace
 
+-- |Get the modification time of a given file.
+getLastModified ∷ FilePath → IO UTCTime
+getLastModified = (clockTimeToUTC <$>) ∘ getModificationTime
+    where
+      clockTimeToUTC ∷ ClockTime → UTCTime
+      clockTimeToUTC (TOD sec picoSec)
+          = posixSecondsToUTCTime
+            $ fromRational
+            $ sec % 1 + picoSec % (1000 ⋅ 1000 ⋅ 1000 ⋅ 1000)
+
 -- |Convert a 'ByteString' to an 'Exp' representing it as a literal.
 liftByteString ∷ ByteString → Q Exp
 liftByteString bs
index ccd50f7eb619edcbef61cf5ad6e91cd083e18f83..a1046c64c86bdcca47b91f5bb4d2686349d6f193 100644 (file)
@@ -7,8 +7,8 @@ type: :task
 component: Lucu
 release: Lucu-1.0
 reporter: PHO <pho@cielonegro.org>
-status: :unstarted
-disposition: 
+status: :closed
+disposition: :fixed
 creation_time: 2011-10-26 23:18:42.168974 Z
 references: []
 
@@ -22,4 +22,12 @@ log_events:
   - PHO <pho@cielonegro.org>
   - edited title, description
   - ""
+- - 2011-11-12 08:01:44.320957 Z
+  - PHO <pho@cielonegro.org>
+  - changed status from unstarted to in_progress
+  - ""
+- - 2011-11-12 09:10:32.315822 Z
+  - PHO <pho@cielonegro.org>
+  - closed with disposition fixed
+  - Done.
 git_branch: