herringbone-wai (empty) → 0.1.0
raw patch · 4 files changed
+159/−0 lines, 4 filesdep +basedep +bytestringdep +herringbonesetup-changed
Dependencies added: base, bytestring, herringbone, http-types, system-fileio, system-filepath, time, wai, wai-app-static
Files
- LICENSE +25/−0
- Setup.hs +2/−0
- Web/Herringbone/Adapter/Wai.hs +104/−0
- herringbone-wai.cabal +28/−0
+ LICENSE view
@@ -0,0 +1,25 @@++The MIT License (MIT)++Copyright (c) 2014 Harry Garrood++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.+++
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Web/Herringbone/Adapter/Wai.hs view
@@ -0,0 +1,104 @@+module Web.Herringbone.Adapter.Wai where++import Control.Monad+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import Data.Time+import Data.Time.Clock.POSIX+import System.Posix.Types (EpochTime)+import Data.Monoid+import Data.List+import Data.Maybe+import Network.Wai+import Network.Wai.Application.Static+import WaiAppStatic.Types+import Network.HTTP.Types+import Prelude hiding (FilePath)+import Filesystem.Path.CurrentOS (FilePath)+import qualified Filesystem.Path.CurrentOS as F+import qualified Filesystem as F++import Web.Herringbone++class ToLazyByteString a where+ toLazyByteString :: a -> BL.ByteString++instance ToLazyByteString FilePath where+ toLazyByteString = toLazyByteString . F.encode++instance ToLazyByteString B.ByteString where+ toLazyByteString = BL.fromChunks . (: [])+++-- | Convert a 'Herringbone' to a WAI 'Application'.+toApplication :: Herringbone -> Application+toApplication hb@(hbDestDir -> dest) =+ staticApp $ (defaultWebAppSettings dest) { ssLookupFile = lookupFile hb }++lookupFile :: Herringbone -> Pieces -> IO LookupResult+lookupFile hb pieces = do+ asset <- findAsset hb (toLogicalPath pieces)+ either assetErrorToLR bundledAssetToLR asset++ where+ assetErrorToLR = return . go++ go AssetNotFound = LRNotFound+ go (AssetCompileError err) = LRFile . assetCompileError $ err+ go (AmbiguousSources xs) = LRFile . ambiguousSources $ xs++ bundledAssetToLR asset = do+ file <- toFile (assetSourcePath asset)+ (assetFilePath asset)+ (last pieces)+ return . LRFile $ file++-- WaiAppStatic takes care of directory traversal attacks for us+toLogicalPath :: Pieces -> LogicalPath+toLogicalPath = unsafeMakeLogicalPath . map fromPiece++-- This is just given to wai-app-static which takes care of serving it.+toFile :: FilePath -- ^ source path+ -> FilePath -- ^ dest path+ -> Piece -- ^ file name+ -> IO File+toFile source dest name = do+ size <- F.getSize dest+ mtime <- F.getModified source+ let strDest = F.encodeString dest+ return File+ { fileGetSize = fromIntegral size+ , fileToResponse = \s h -> responseFile s h strDest Nothing+ , fileName = name+ , fileGetHash = return Nothing -- TODO+ , fileGetModified = Just . toEpochTime $ mtime+ }++toEpochTime :: UTCTime -> EpochTime+toEpochTime = fromIntegral . toSecs+ where+ toSecs :: UTCTime -> Int+ toSecs = floor . utcTimeToPOSIXSeconds++assetCompileError :: CompileError -> File+assetCompileError err =+ fileError (toLazyByteString err) (unsafeToPiece "compile-error.html")++ambiguousSources :: [FilePath] -> File+ambiguousSources sources =+ let body = "<h1>Ambiguous asset source</h1>" <>+ "<p>List of possible asset sources:</p>" <>+ "<ul>" <>+ BL.concat (map (\s -> "<li>" <> toLazyByteString s <> "</li>") sources) <>+ "</ul>"+ in fileError body (unsafeToPiece "error-ambiguous-source.html")++fileError :: BL.ByteString -> Piece -> File+fileError body name =+ File+ { fileGetSize = fromIntegral $ BL.length body+ , fileToResponse = \_ headers -> responseLBS status500 headers body+ , fileName = name+ , fileGetHash = return Nothing+ , fileGetModified = Nothing+ }
+ herringbone-wai.cabal view
@@ -0,0 +1,28 @@+name: herringbone-wai+version: 0.1.0+synopsis: Wai adapter for the Herringbone web asset preprocessor.+description: Wai adapter for the Herringbone web asset preprocessor.+license: MIT+license-file: LICENSE+author: Harry Garrood+maintainer: harry@garrood.me+-- copyright:+category: Web+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10++library+ exposed-modules: Web.Herringbone.Adapter.Wai+ build-depends: base >=4.6 && <5,+ herringbone,+ wai >= 3.0,+ wai-app-static,+ time,+ system-filepath,+ system-fileio,+ bytestring,+ http-types+ default-extensions: OverloadedStrings,+ ViewPatterns+ default-language: Haskell2010