on master help sign in
Add 'wai-frontend-monadcgi/' from commit '9dbc92c5b589139f417662c561727b57bd68a11b'

git-subtree-dir: wai-frontend-monadcgi git-subtree-mainline: 36722c8dac179417fc3095341daf7ed983e74128 git-subtree-split: 9dbc92c5b589139f417662c561727b57bd68a11b

commitd0fb59814bdd82ad1c14684c7adbd395f847a73b authorMichael Snoyman <michael@snoyman.com> dateFri 6 Jan 2012, 12:38 (15 years ago) parent36722c89dbc92c
11 files changed+183
wai-frontend-monadcgi/.gitignore+2 wai-frontend-monadcgi/LICENSE+25 wai-frontend-monadcgi/Network/Wai/Frontend/MonadCGI.hs+79 wai-frontend-monadcgi/README+1 wai-frontend-monadcgi/Setup.lhs+7 wai-frontend-monadcgi/samples/.htaccess+5 wai-frontend-monadcgi/samples/plain_cgi.hs+5 wai-frontend-monadcgi/samples/wai_cgi.hs+8 wai-frontend-monadcgi/samples/wai_cgi_generic.hs+19 wai-frontend-monadcgi/samples/wai_fastcgi.hs+8 wai-frontend-monadcgi/wai-frontend-monadcgi.cabal+24
wai-frontend-monadcgi/.gitignorenew file+2
@@ -0,0 +1,2 @@
1+dist
2+*.swp
wai-frontend-monadcgi/LICENSEnew file+25
@@ -0,0 +1,25 @@
1+The following license covers this documentation, and the source code, except
2+where otherwise indicated.
3+
4+Copyright 2008, Michael Snoyman. All rights reserved.
5+
6+Redistribution and use in source and binary forms, with or without
7+modification, are permitted provided that the following conditions are met:
8+
9+* Redistributions of source code must retain the above copyright notice, this
10+ list of conditions and the following disclaimer.
11+
12+* Redistributions in binary form must reproduce the above copyright notice,
13+ this list of conditions and the following disclaimer in the documentation
14+ and/or other materials provided with the distribution.
15+
16+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
17+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
20+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
wai-frontend-monadcgi/Network/Wai/Frontend/MonadCGI.hsnew file+79
@@ -0,0 +1,79 @@
1+module Network.Wai.Frontend.MonadCGI
2+ ( cgiToApp
3+ , cgiToAppGeneric
4+ ) where
5+
6+import Network.Wai
7+import Network.CGI.Monad
8+import Network.CGI.Protocol
9+import Network.HTTP.Types (Status (..))
10+import Control.Monad.IO.Class (liftIO)
11+import Data.CaseInsensitive (original)
12+
13+import Data.Conduit
14+import Data.Conduit.Lazy (lazyConsume)
15+
16+import qualified Data.Map as Map
17+import qualified Data.ByteString.Lazy as BS
18+import qualified Data.ByteString.Char8 as S8
19+
20+import Control.Arrow (first)
21+import Data.Char (toUpper)
22+import Data.String (fromString)
23+
24+safeRead :: Read a => a -> String -> a
25+safeRead d s = case reads s of
26+ ((x, _):_) -> x
27+ _ -> d
28+
29+cgiToApp :: CGI CGIResult -> Application
30+cgiToApp = cgiToAppGeneric id
31+
32+unbufferSource :: Monad m => BufferedSource m a -> Source m a
33+unbufferSource bsrc = Source $ return $ PreparedSource
34+ { sourcePull = bsourcePull bsrc
35+ , sourceClose = bsourceClose bsrc
36+ }
37+
38+cgiToAppGeneric :: Monad m
39+ => (m (Headers, CGIResult) -> IO (Headers, CGIResult))
40+ -> CGIT m CGIResult
41+ -> Application
42+cgiToAppGeneric toIO cgi env = do
43+ input <- fmap BS.fromChunks $ lazyConsume $ unbufferSource $ requestBody env
44+ let vars = map (first fixVarName . go) (requestHeaders env)
45+ ++ getCgiVars env
46+ (inputs, body') = decodeInput vars input
47+ req = CGIRequest
48+ { cgiVars = Map.fromList $ vars
49+ , cgiInputs = inputs
50+ , cgiRequestBody = body'
51+ }
52+ (headers'', output') <- liftIO $ toIO $ runCGIT cgi req
53+ let output = case output' of
54+ CGIOutput bs -> bs
55+ CGINothing -> BS.empty
56+ let headers' = map (\(HeaderName x, y) ->
57+ (fromString x, S8.pack y)) headers''
58+ let status' = case lookup (fromString "Status") headers' of
59+ Nothing -> 200
60+ Just s -> safeRead 200 $ S8.unpack s
61+ return $ responseLBS (Status status' S8.empty) headers' output
62+ where
63+ go (x, y) = (S8.unpack $ original x, S8.unpack y)
64+
65+fixVarName :: String -> String
66+fixVarName = ((++) $ "HTTP_") . map fixVarNameChar
67+
68+fixVarNameChar :: Char -> Char
69+fixVarNameChar '-' = '_'
70+fixVarNameChar c = toUpper c
71+
72+getCgiVars :: Request -> [(String, String)]
73+getCgiVars e =
74+ [ ("PATH_INFO", S8.unpack $ rawPathInfo e)
75+ , ("REQUEST_METHOD", show $ requestMethod e)
76+ , ("QUERY_STRING", S8.unpack $ rawQueryString e)
77+ , ("SERVER_NAME", S8.unpack $ serverName e)
78+ , ("SERVER_PORT", show $ serverPort e)
79+ ]
wai-frontend-monadcgi/READMEnew file+1
@@ -0,0 +1 @@
1+Run CGI apps on WAI handlers.
wai-frontend-monadcgi/Setup.lhsnew file+7
@@ -0,0 +1,7 @@
1+#!/usr/bin/env runhaskell
2+
3+> module Main where
4+> import Distribution.Simple
5+
6+> main :: IO ()
7+> main = defaultMain
wai-frontend-monadcgi/samples/.htaccessnew file+5
@@ -0,0 +1,5 @@
1+Options +ExecCGI
2+AddHandler cgi-script .cgi
3+AddHandler fastcgi-script .fcgi
4+
5+Options +FollowSymlinks
wai-frontend-monadcgi/samples/plain_cgi.hsnew file+5
@@ -0,0 +1,5 @@
1+import Network.CGI
2+
3+main = runCGI mainCGI
4+
5+mainCGI = output "This is a test"
wai-frontend-monadcgi/samples/wai_cgi.hsnew file+8
@@ -0,0 +1,8 @@
1+import qualified Network.CGI
2+import qualified Network.Wai.Handler.SimpleServer
3+import qualified Network.Wai.Frontend.MonadCGI
4+
5+main = Network.Wai.Handler.SimpleServer.run 3000
6+ $ Network.Wai.Frontend.MonadCGI.cgiToApp mainCGI
7+
8+mainCGI = Network.CGI.output "This is a test"
wai-frontend-monadcgi/samples/wai_cgi_generic.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE PackageImports #-}
2+import qualified Network.CGI
3+import qualified Network.Wai.Handler.SimpleServer
4+import qualified Network.Wai.Frontend.MonadCGI
5+import "mtl" Control.Monad.Reader
6+
7+main :: IO ()
8+main = Network.Wai.Handler.SimpleServer.run 3000
9+ $ Network.Wai.Frontend.MonadCGI.cgiToAppGeneric
10+ monadToIO
11+ mainCGI
12+
13+mainCGI :: Network.CGI.CGIT (Reader String) Network.CGI.CGIResult
14+mainCGI = do
15+ s <- lift ask
16+ Network.CGI.output s
17+
18+monadToIO :: Reader String a -> IO a
19+monadToIO = return . (flip runReader) "This is a generic test"
wai-frontend-monadcgi/samples/wai_fastcgi.hsnew file+8
@@ -0,0 +1,8 @@
1+import qualified Network.CGI
2+import qualified Network.Wai.Handler.FastCGI
3+import qualified Network.Wai.Frontend.MonadCGI
4+
5+main = Network.Wai.Handler.FastCGI.run
6+ $ Network.Wai.Frontend.MonadCGI.cgiToApp mainCGI
7+
8+mainCGI = Network.CGI.output "This is a test"
wai-frontend-monadcgi/wai-frontend-monadcgi.cabalnew file+24
@@ -0,0 +1,24 @@
1+name: wai-frontend-monadcgi
2+version: 0.2.0
3+license: BSD3
4+license-file: LICENSE
5+author: Michael Snoyman <michael@snoyman.com>
6+maintainer: Michael Snoyman <michael@snoyman.com>
7+synopsis: Allows programs written against MonadCGI to run with any WAI handler. (deprecated)
8+category: Web
9+stability: stable
10+cabal-version: >= 1.2
11+build-type: Simple
12+
13+library
14+ build-depends: base >= 4 && < 5,
15+ bytestring,
16+ containers >= 0.2,
17+ cgi,
18+ conduit,
19+ http-types,
20+ transformers,
21+ case-insensitive,
22+ wai >= 1.0 && < 1.1
23+ exposed-modules: Network.Wai.Frontend.MonadCGI
24+ ghc-options: -Wall