packages feed

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 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 @@+![GitHub Actions status](https://github.com/kazu-yamamoto/wai-app-file-cgi/workflows/Haskell%20CI/badge.svg)
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