checkPieces ss@StaticSettings {..} pieces req = do
    res <- lookupResult
    case res of
        Left location -> return $ RawRedirect location
        Right LRNotFound -> return NotFound
        Right (LRFile file) -> serveFile ss req file
        Right (LRFolder folder) -> serveFolder ss pieces req folder
  where
    lookupResult :: IO (Either ByteString LookupResult)
    lookupResult = do
      nonIndexResult <- ssLookupFile pieces
      case nonIndexResult of
          LRFile{} -> return $ Right nonIndexResult
          _ -> do
              eIndexResult <- lookupIndices (map (\ index -> dropLastIfNull pieces ++ [index]) ssIndices)
              return $ case eIndexResult of
                  Left redirect -> Left redirect
                  Right indexResult -> case indexResult of
                      LRNotFound -> Right nonIndexResult
                      LRFile file | ssRedirectToIndex ->
                          let relPath =
                                  case reverse pieces of
                                      -- Served at root
                                      [] -> fromPiece $ fileName file
                                      lastSegment:_ ->
                                          case fromPiece lastSegment of
                                              -- Ends with a trailing slash
                                              "" -> fromPiece $ fileName file
                                              -- Lacks a trailing slash
                                              lastSegment' -> T.concat
                                                  [ lastSegment'
                                                  , "/"
                                                  , fromPiece $ fileName file
                                                  ]
                           in Left $ TE.encodeUtf8 relPath
                      _ -> Right indexResult

    lookupIndices :: [Pieces] -> IO (Either ByteString LookupResult)
    lookupIndices (x : xs) = do
        res <- ssLookupFile x
        case res of
            LRNotFound -> lookupIndices xs
            _ -> return $ case (ssAddTrailingSlash, addTrailingSlash req) of
                (True, Just redirect) -> Left redirect
                _ -> Right res
    lookupIndices [] = return $ Right LRNotFound
checkPieces ss@StaticSettings {..} pieces req = do
    res <- lookupResult
    case res of
        Left location -> return $ RawRedirect location
        Right LRNotFound -> return NotFound
        Right (LRFile file) -> serveFile ss req file
        Right (LRFolder folder) -> serveFolder ss pieces req folder
  where
    lookupResult :: IO (Either ByteString LookupResult)
    lookupResult = do
      nonIndexResult <- ssLookupFile pieces
      case nonIndexResult of
          LRFile{} -> return $ Right nonIndexResult
          _ -> do
              eIndexResult <- lookupIndices (map (\ index -> dropLastIfNull pieces ++ [index]) ssIndices)
              return $ case eIndexResult of
                  Left redirect -> Left redirect
                  Right indexResult -> case indexResult of
                      LRNotFound -> Right nonIndexResult
                      LRFile file | ssRedirectToIndex ->
                          let relPath =
                                  case reverse pieces of
                                      -- Served at root
                                      [] -> fromPiece $ fileName file
                                      lastSegment:_ ->
                                          case fromPiece lastSegment of
                                              -- Ends with a trailing slash
                                              "" -> fromPiece $ fileName file
                                              -- Lacks a trailing slash
                                              lastSegment' -> T.concat
                                                  [ lastSegment'
                                                  , "/"
                                                  , fromPiece $ fileName file
                                                  ]
                           in Left $ TE.encodeUtf8 relPath
                      _ -> Right indexResult

    lookupIndices :: [Pieces] -> IO (Either ByteString LookupResult)
    lookupIndices (x : xs) = do
        res <- ssLookupFile x
        case res of
            LRNotFound -> lookupIndices xs
            _ -> return $ case (ssAddTrailingSlash, addTrailingSlash req) of
                (True, Just redirect) -> Left redirect
                _ -> Right res
    lookupIndices [] = return $ Right LRNotFound
checkPieces ss@StaticSettings {..} pieces req = do
    res <- lookupResult
    case res of
        Left location -> return $ RawRedirect location
        Right LRNotFound -> return NotFound
        Right (LRFile file) -> serveFile ss req file
        Right (LRFolder folder) -> serveFolder ss pieces req folder
  where
    lookupResult :: IO (Either ByteString LookupResult)
    lookupResult = do
      nonIndexResult <- ssLookupFile pieces
      case nonIndexResult of
          LRFile{} -> return $ Right nonIndexResult
          _ -> do
              eIndexResult <- lookupIndices (map (\ index -> dropLastIfNull pieces ++ [index]) ssIndices)
              return $ case eIndexResult of
                  Left redirect -> Left redirect
                  Right indexResult -> case indexResult of
                      LRNotFound -> Right nonIndexResult
                      LRFile file | ssRedirectToIndex ->
                          let relPath =
                                  case reverse pieces of
                                      -- Served at root
                                      [] -> fromPiece $ fileName file
                                      lastSegment:_ ->
                                          case fromPiece lastSegment of
                                              -- Ends with a trailing slash
                                              "" -> fromPiece $ fileName file
                                              -- Lacks a trailing slash
                                              lastSegment' -> T.concat
                                                  [ lastSegment'
                                                  , "/"
                                                  , fromPiece $ fileName file
                                                  ]
                           in Left $ TE.encodeUtf8 relPath
                      _ -> Right indexResult

    lookupIndices :: [Pieces] -> IO (Either ByteString LookupResult)
    lookupIndices (x : xs) = do
        res <- ssLookupFile x
        case res of
            LRNotFound -> lookupIndices xs
            _ -> return $ case (ssAddTrailingSlash, addTrailingSlash req) of
                (True, Just redirect) -> Left redirect
                _ -> Right res
    lookupIndices [] = return $ Right LRNotFound