wai-app-file-cgi 3.1.12 → 3.2.0
raw patch · 8 files changed
+124/−9 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +16/−0
- Network/Wai/Application/Classic/FileInfo.hs +48/−2
- Network/Wai/Application/Classic/Types.hs +25/−2
- README.md +1/−0
- test/ClassicSpec.hs +10/−1
- test/Spec.hs +8/−2
- test/cgi-bin/index.cgi +10/−0
- wai-app-file-cgi.cabal +6/−2
+ CHANGELOG.md view
@@ -0,0 +1,16 @@+# ChangeLog for wai-app-file-cgi++## 3.2.0++- `FileRoute`s now allow routing a requested path directly to a file+ instead of just path prefixes to directories. For this, paths that+ don't have a trailing path separator are interpreted as paths to+ a file.++ This change may **break** existing `FileRoute`s if they lack the+ trailing path separator. Before upgrading, make sure that all+ `FileRoute`s (that work correctly with `wai-app-file-cgi < 3.2`)+ have trailing path separators in the `fileSrc` and `fileDst`+ record fields.++ See also [#23](https://github.com/kazu-yamamoto/wai-app-file-cgi/pull/23).
Network/Wai/Application/Classic/FileInfo.hs view
@@ -1,19 +1,65 @@ module Network.Wai.Application.Classic.FileInfo where +import qualified Data.ByteString as BS import Network.Wai import Network.Wai.Application.Classic.Path import Network.Wai.Application.Classic.Types ---------------------------------------------------------------- +{- $setup+>>> :set -XOverloadedStrings+>>> import Network.Wai (defaultRequest)+>>> import Network.Wai.Internal (Request (..))+>>> mkReq p = defaultRequest { rawPathInfo = p }+>>> import Network.Wai.Application.Classic.Def (defaultFileAppSpec)+-}++{- |+>>> pathinfoToFilePath (mkReq "/") (FileRoute "/" "/srv/http")+"/srv/http"+>>> pathinfoToFilePath (mkReq "/") (FileRoute "/" "/srv/http/")+"/srv/http/"+>>> pathinfoToFilePath (mkReq "/hello") (FileRoute "/" "/srv/http/")+"/srv/http/hello"+>>> pathinfoToFilePath (mkReq "/hello/") (FileRoute "/" "/srv/http/")+"/srv/http/hello/"+>>> pathinfoToFilePath (mkReq "/about/wai.html") (FileRoute "/" "/srv/http/")+"/srv/http/about/wai.html"+>>> pathinfoToFilePath (mkReq "/hello/") (FileRoute "/sub/dir/" "/var/root/")+"/var/root/"+>>> pathinfoToFilePath (mkReq "/sub/dir/") (FileRoute "/sub/dir/" "/var/root/")+"/var/root/"+>>> pathinfoToFilePath (mkReq "/sub/dir/test.html") (FileRoute "/sub/dir/" "/var/root/")+"/var/root/test.html"+>>> pathinfoToFilePath (mkReq "/exact/match") (FileRoute "/exact/match" "/tmp/dst")+"/tmp/dst"+>>> pathinfoToFilePath (mkReq "/exact/match/") (FileRoute "/exact/match" "/tmp/dst")+"/tmp/dst/"+>>> pathinfoToFilePath (mkReq "/exact/match/more.html") (FileRoute "/exact/match" "/tmp/dst")+"/tmp/dst/more.html"+-} pathinfoToFilePath :: Request -> FileRoute -> Path-pathinfoToFilePath req filei = path'+pathinfoToFilePath req filei+ | BS.null path' = dst+ | otherwise = dst </> path' where path = rawPathInfo req src = fileSrc filei dst = fileDst filei- path' = dst </> (path <\> src) -- fixme+ path' = path <\> src +{- |++It matters to 'pathinfoToFilePath' whether the 'FileRoute' has trailing slashes+which also influences 'addIndex':++>>> addIndex defaultFileAppSpec (pathinfoToFilePath (mkReq "/exact/match.html") (FileRoute "/exact/match.html" "/some/file.html"))+"/some/file.html"+>>> addIndex defaultFileAppSpec (pathinfoToFilePath (mkReq "/some/dir") (FileRoute "/some/dir/" "/target/dir/"))+"/target/dir/index.html"++-} addIndex :: FileAppSpec -> Path -> Path addIndex spec path | hasTrailingPathSeparator path = path </> indexFile spec
Network/Wai/Application/Classic/Types.hs view
@@ -34,10 +34,33 @@ , isHTML :: Path -> Bool } +-- | 'FileRoute' describes the relationship between Paths requested via HTTP+-- and paths to serve on disk. Specifically, it maps a /single/ path+-- prefix to a destination path, so the 'FileRoute' needs to be applicable+-- to the current request,+-- e.g. @FileRoute "\/static\/" "\/var\/www\/static\/"@ will yield a 404 if+-- @"/page.html"@ is requested.+-- In the simplest case @FileRoute "\/" "\/var\/www\/"@ routes everything+-- to a single destination path.+--+-- When resolving routes, no filesystem reads are performed, so path+-- type needs to be inferred from the path.+--+-- * If 'fileSrc' and 'fileDst' have a trailing slash, source and+-- destination are assumed to be directories (this e.g. enables+-- fallback to index files).+--+-- * If 'fileSrc' and 'fileDst' lack a trailing slash, they are+-- assumed to be files. This is supported since 3.2.0.+--+-- If the path type inferrable from 'FileRoute' does not match+-- the type of the destination path on disk, routes will not+-- resolve correctly. If the inferrable type doesn't match+-- between 'fileSrc' and 'fileDst', routing may also misbehave. data FileRoute = FileRoute {- -- | Path prefix to be matched to 'rawPathInfo'.+ -- | Path (prefix) to be matched to 'rawPathInfo'. fileSrc :: Path- -- | Path prefix to an actual file system.+ -- | Path to the target directory or file. , fileDst :: Path } deriving (Eq,Show)
+ README.md view
@@ -0,0 +1,1 @@+
test/ClassicSpec.hs view
@@ -14,12 +14,16 @@ spec :: Spec spec = do describe "cgiApp" $ do+ it "returns index.cgi with empty PATH_INFO for /cgi-bin/" $ do+ let url = "http://127.0.0.1:2345/cgi-bin/"+ bdy <- rspBody <$> sendGET url+ bdy `shouldBe` "index.cgi\n" it "accepts POST" $ do let url = "http://127.0.0.1:2345/cgi-bin/echo-env/pathinfo?query=foo" bdy <- rspBody <$> sendPOST url "foo bar.\nbaz!\n" ans <- readFileAscii "test/data/post" bdy `shouldBe` ans- it "causes 500 if the CGI script does not exist" $ do+ it "causes 500 if the CGI script does not behave correctly" $ do let url = "http://127.0.0.1:2345/cgi-bin/broken" sc <- rspCode <$> sendPOST url "foo bar.\nbaz!\n" sc `shouldBe` (5,0,0)@@ -85,6 +89,11 @@ Just lm = lookupHeader HdrLocation hdr sc `shouldBe` (3,0,1) lm `shouldBe` "//127.0.0.1:2345/redirect/"+ it "returns index.html for /exact-route.html matching exactRoute" $ do+ let url = "http://127.0.0.1:2345/exact-route.html"+ bdy <- rspBody <$> sendGET url+ ans <- readFileAscii "test/html/index.html"+ bdy `shouldBe` ans ----------------------------------------------------------------
test/Spec.hs view
@@ -30,14 +30,20 @@ testApp :: FilePath -> Application testApp dir req- | cgi = cgiApp appSpec defaultCgiAppSpec cgiRoute req- | otherwise = fileApp appSpec defaultFileAppSpec fileRoute req+ | cgi = cgiApp appSpec defaultCgiAppSpec cgiRoute req+ | exact = fileApp appSpec defaultFileAppSpec exactRoute req+ | otherwise = fileApp appSpec defaultFileAppSpec fileRoute req where cgi = "/cgi-bin/" `BS.isPrefixOf` rawPathInfo req+ exact = "/exact-route.html" `BS.isPrefixOf` rawPathInfo req appSpec = defaultClassicAppSpec { softwareName = "ClassicTester" } cgiRoute = CgiRoute { cgiSrc = "/cgi-bin/" , cgiDst = fromString (dir </> "test/cgi-bin/")+ }+ exactRoute = FileRoute {+ fileSrc = "/exact-route.html"+ , fileDst = fromString (dir </> "test/html/index.html") } fileRoute = FileRoute { fileSrc = "/"
+ test/cgi-bin/index.cgi view
@@ -0,0 +1,10 @@+#!/bin/sh++echo "Content-Type: text/plain"+echo "Status: 200"+echo ""+if test -n "$PATH_INFO"; then+ echo "PATH_INFO: $PATH_INFO"+else+ echo "index.cgi"+fi
wai-app-file-cgi.cabal view
@@ -1,6 +1,6 @@-cabal-version: >=1.10+cabal-version: 1.18 name: wai-app-file-cgi-version: 3.1.12+version: 3.2.0 license: BSD3 license-file: LICENSE maintainer: Kazu Yamamoto <kazu@iij.ad.jp>@@ -14,7 +14,11 @@ category: Web, Yesod build-type: Simple+extra-doc-files:+ README.md+ CHANGELOG.md extra-source-files:+ test/cgi-bin/index.cgi test/cgi-bin/broken test/cgi-bin/echo-env test/data/post