diff --git a/Network/Wai/Application/Static.hs b/Network/Wai/Application/Static.hs
--- a/Network/Wai/Application/Static.hs
+++ b/Network/Wai/Application/Static.hs
@@ -99,7 +99,7 @@
 import Data.Ord (comparing)
 import qualified Data.ByteString.Base64 as B64
 import Data.Either (rights)
-import Data.Maybe (isJust, fromJust)
+import Data.Maybe (isJust, fromJust, mapMaybe)
 import Network.HTTP.Date (parseHTTPDate, epochTimeToHTTPDate, formatHTTPDate)
 import Data.String (IsString (..))
 
@@ -114,7 +114,7 @@
 -- | A list of all possible extensions, starting from the largest.
 takeExtensions :: FilePath -> [FilePath]
 takeExtensions (FilePath s) =
-    case T.break (== '.') s of
+    case T.breakOn (".") s of
         (_, "") -> []
         (_, x) -> FilePath (T.drop 1 x) : takeExtensions (FilePath $ T.drop 1 x)
 
@@ -192,37 +192,26 @@
   ( "xwd"     , "image/x-xwindowdump"               ),
   ( "zip"     , "application/zip"                   )]
 
+-- similar to Safe package
+headDef :: a -> [a] -> a
+headDef _ (x:_) = x
+headDef def []  = def
+
+-- similar to Safe package
+initSafe  :: [a] -> [a]
+initSafe [] = []
+initSafe xs = init xs
+
 mimeTypeByExt :: MimeMap
               -> MimeType -- ^ default mime type
               -> FilePath
               -> MimeType
 mimeTypeByExt mm def =
-    go . takeExtensions
-  where
-    go [] = def
-    go (e:es) =
-        case Map.lookup e mm of
-            Nothing -> go es
-            Just mt -> mt
+  headDef def . mapMaybe (flip Map.lookup mm) . takeExtensions
 
 defaultMimeTypeByExt :: FilePath -> MimeType
 defaultMimeTypeByExt = mimeTypeByExt defaultMimeTypes defaultMimeType
 
-data CheckPieces =
-      -- | Just the etag hash or Nothing for no etag hash
-      Redirect Pieces (Maybe ByteString)
-    | Forbidden
-    | NotFound
-    | FileResponse File H.ResponseHeaders
-    | NotModified
-    | DirectoryResponse Folder
-    -- TODO: add file size
-    | SendContent MimeType L.ByteString
-
-safeInit  :: [a] -> [a]
-safeInit [] = []
-safeInit xs = init xs
-
 filterButLast :: (a -> Bool) -> [a] -> [a]
 filterButLast _ [] = []
 filterButLast _ [x] = [x]
@@ -231,8 +220,8 @@
     | otherwise = filterButLast f xs
 
 
-unsafe :: FilePath -> Bool
-unsafe (FilePath s)
+unsafePiece :: FilePath -> Bool
+unsafePiece (FilePath s)
     | T.null s = False
     | T.head s == '.' = True
     | otherwise = T.any (== '/') s
@@ -262,6 +251,17 @@
     Just $ SendContent "image/png" $ L.fromChunks [$(embedFile "images/haskell.png")]
 checkSpecialDirListing _ =  Nothing
 
+data CheckPieces =
+      -- | Just the etag hash or Nothing for no etag hash
+      Redirect Pieces (Maybe ByteString)
+    | Forbidden
+    | NotFound
+    | FileResponse File H.ResponseHeaders
+    | NotModified
+    | DirectoryResponse Folder
+    -- TODO: add file size
+    | SendContent MimeType L.ByteString
+
 checkPieces :: (Pieces -> IO FileLookup) -- ^ file lookup function
             -> [FilePath]                -- ^ List of default index files. Cannot contain slashes.
             -> Pieces                    -- ^ parsed request
@@ -271,16 +271,14 @@
             -> Bool                      -- ^ Redirect to Index?
             -> IO CheckPieces
 checkPieces fileLookup indices pieces req maxAge useHash redirectToIndex
-    | any unsafe pieces = return Forbidden
-    | any nullFilePath $ safeInit pieces =
+    | any unsafePiece pieces = return Forbidden
+    | any nullFilePath $ initSafe pieces =
         return $ Redirect (filterButLast (not . nullFilePath) pieces) Nothing
     | otherwise = do
         let (isFile, isFolder) =
-                case () of
-                    ()
-                        | null pieces -> (True, True)
-                        | nullFilePath (last pieces) -> (False, True)
-                        | otherwise -> (True, False)
+              if        null pieces                then (True, True)
+                else if nullFilePath (last pieces) then (False, True)
+                                                   else (True, False)
 
         fl <- fileLookup pieces
         case (fl, isFile) of
@@ -368,9 +366,7 @@
     checkIndices :: [FilePath] -> Maybe FilePath
     checkIndices contents = find (flip elem indices) contents
 
-    cacheControl = case ccInt of
-        Nothing -> []
-        Just i  -> [("Cache-Control", S8.append "max-age=" $ S8.pack $ show i)]
+    cacheControl = headerCacheControl $ headerExpires []
       where
         ccInt =
             case maxAge of
@@ -380,6 +376,16 @@
         oneYear :: Int
         oneYear = 60 * 60 * 24 * 365
 
+        headerCacheControl =
+          case ccInt of
+            Nothing -> id
+            Just i  -> (:) ("Cache-Control", S8.append "public, max-age=" $ S8.pack $ show i)
+        headerExpires =
+          case maxAge of
+            NoMaxAge        -> id
+            MaxAgeSeconds _ -> id -- FIXME
+            MaxAgeForever   -> (:) ("Expires", "Thu, 31 Dec 2037 23:55:55 GMT")
+
 type Listing = (Pieces -> Folder -> IO L.ByteString)
 
 
@@ -613,7 +619,13 @@
     let indices = ssIndices ss
     case checkSpecialDirListing pieces of
          Just res ->  response res
-         Nothing  ->  checkPieces (ssFolder ss) (map FilePath indices) pieces req (ssMaxAge ss) (ssUseHash ss) (ssRedirectToIndex ss) >>= response
+         Nothing  ->  response =<< checkPieces (ssFolder ss)
+                                  (map FilePath indices)
+                                  pieces
+                                  req
+                                  (ssMaxAge ss)
+                                  (ssUseHash ss)
+                                  (ssRedirectToIndex ss)
   where
     response cp = case cp of
         FileResponse file ch -> do
diff --git a/test/WaiAppStaticTest.hs b/test/WaiAppStaticTest.hs
--- a/test/WaiAppStaticTest.hs
+++ b/test/WaiAppStaticTest.hs
@@ -90,7 +90,7 @@
     it "Cache-Control set when etag parameter is correct" $ webApp $ do
       req <- request statFile { queryString = [("etag", Just etag)] }
       assertStatus 200 req
-      assertHeader "Cache-Control" "max-age=31536000" req
+      assertHeader "Cache-Control" "public, max-age=31536000" req
       assertNoHeader "Last-Modified" req
 
     it "200 when invalid in-none-match sent" $ webApp $
diff --git a/wai-app-static.cabal b/wai-app-static.cabal
--- a/wai-app-static.cabal
+++ b/wai-app-static.cabal
@@ -1,5 +1,5 @@
 name:            wai-app-static
-version:         1.2.0.3
+version:         1.2.0.4
 license:         MIT
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>
