wai-handler-fastcgi-1.3.0.2/0000755000000000000000000000000012110452445013650 5ustar0000000000000000wai-handler-fastcgi-1.3.0.2/fastcgi.buildinfo.in0000644000000000000000000000011412110452445017566 0ustar0000000000000000ghc-options: -optc@CPPFLAGS@ cc-options: @CPPFLAGS@ ld-options: @LDFLAGS@ wai-handler-fastcgi-1.3.0.2/wai-handler-fastcgi.cabal0000644000000000000000000000203512110452445020445 0ustar0000000000000000name: wai-handler-fastcgi version: 1.3.0.2 license: MIT license-file: LICENSE author: Michael Snoyman maintainer: Michael Snoyman synopsis: Wai handler to fastcgi category: Web stability: stable cabal-version: >= 1.6 build-type: Configure extra-source-files: configure fastcgi.buildinfo.in homepage: http://www.yesodweb.com/book/web-application-interface description: Calls out to the libfcgi C library. library build-depends: base >= 4 && < 5 , wai >= 1.3 && < 1.5 , wai-extra >= 1.3 && < 1.4 , bytestring >= 0.9.1.4 exposed-modules: Network.Wai.Handler.FastCGI ghc-options: -Wall includes: fcgiapp.h extra-libraries: fcgi if impl(ghc >= 7.4) cpp-options: -DGHC_7_4 source-repository head type: git location: git://github.com/yesodweb/wai.git wai-handler-fastcgi-1.3.0.2/LICENSE0000644000000000000000000000207512110452445014661 0ustar0000000000000000Copyright (c) 2012 Michael Snoyman, http://www.yesodweb.com/ 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. wai-handler-fastcgi-1.3.0.2/Setup.lhs0000644000000000000000000000016212110452445015457 0ustar0000000000000000#!/usr/bin/env runhaskell > module Main where > import Distribution.Simple > main :: IO () > main = defaultMain wai-handler-fastcgi-1.3.0.2/configure0000644000000000000000000000040312110452445015551 0ustar0000000000000000#!/bin/sh # # subst standard header path variables if test -n "$CPPFLAGS" ; then echo "Found CPPFLAGS in environment: '$CPPFLAGS'" sed 's,@CPPFLAGS@,'"$CPPFLAGS"',g;s,@LDFLAGS@,'"$LDFLAGS"',g' \ < fastcgi.buildinfo.in > fastcgi.buildinfo fi wai-handler-fastcgi-1.3.0.2/Network/0000755000000000000000000000000012110452445015301 5ustar0000000000000000wai-handler-fastcgi-1.3.0.2/Network/Wai/0000755000000000000000000000000012110452445016021 5ustar0000000000000000wai-handler-fastcgi-1.3.0.2/Network/Wai/Handler/0000755000000000000000000000000012110452445017376 5ustar0000000000000000wai-handler-fastcgi-1.3.0.2/Network/Wai/Handler/FastCGI.hsc0000644000000000000000000001346212110452445021323 0ustar0000000000000000{-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : Network.Wai.Handler.FastCGI -- Copyright : (c) Bjorn Bringert 2004-2005, (c) Lemmih 2006, (c) Michael Snoyman 2010 -- License : BSD-style (see the file libraries/network/LICENSE) -- -- Maintainer : michael@snoyman.com -- Stability : experimental -- Portability : non-portable (uses FFI) -- -- Interface for FastCGI , using the fcgiapp API. -- Totally ripped off by Michael Snoyman to work with Hack, then WAI. -- ----------------------------------------------------------------------------- module Network.Wai.Handler.FastCGI ( run , runSendfile , runFork ) where import Control.Monad ( liftM, forever ) import Data.Word (Word8) import Foreign ( Ptr, castPtr, nullPtr, peekArray0 , throwIfNeg_, mallocBytes, free ) #ifdef GHC_7_4 import Foreign.C (CInt(..), CString, CStringLen) #else import Foreign.C (CInt, CString, CStringLen) #endif import Control.Exception (finally) import Foreign.Storable ( Storable (..) ) import qualified Network.Wai as W import qualified Network.Wai.Handler.CGI as CGI import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as S8 import qualified Data.ByteString as BS import qualified Data.ByteString.Internal as BSB import qualified Data.ByteString.Unsafe as BSB import Control.Arrow ((***)) #include ------------------------------------------------------------------------ data FCGX_Stream type StreamPtr = Ptr FCGX_Stream type Environ = Ptr CString ------------------------------------------------------------------------ foreign import ccall unsafe "fcgiapp.h FCGX_GetStr" fcgx_getStr :: CString -> CInt -> StreamPtr -> IO CInt foreign import ccall unsafe "fcgiapp.h FCGX_PutStr" fcgx_putStr :: CString -> CInt -> StreamPtr -> IO CInt ------------------------------------------------------------------------ foreign import ccall unsafe "fcgiapp.h FCGX_Init" fcgx_init :: IO CInt runFork :: Maybe S.ByteString -> (IO () -> IO a) -> Int -> W.Application -> IO () runFork sf fork threads app = do testReturn "FCGX_Init" $ fcgx_init let oneThread = forever $ oneRequest app sf mapM_ fork $ replicate (threads - 1) oneThread oneThread -- | Handle FastCGI requests in an infinite loop. run :: W.Application -> IO () run = runFork Nothing id 1 -- | Handle FastCGI requests in an infinite loop. For a server which supports -- the X-Sendfile header. runSendfile :: S.ByteString -> W.Application -> IO () runSendfile sf = runFork (Just sf) id 1 oneRequest :: W.Application -> Maybe S.ByteString -- X-Sendfile -> IO () oneRequest app xsendfile = withRequest $ \r -> do putStrLn "Received 1 request" env <- peekEnvp r ins <- peekIn r outs <- peekOut r handleRequest app ins outs env xsendfile peekIn, peekOut :: Ptr FCGX_Request -> IO (Ptr FCGX_Stream) peekIn = (#peek FCGX_Request, in) peekOut = (#peek FCGX_Request, out) peekEnvp :: Ptr FCGX_Request -> IO Environ peekEnvp = (#peek FCGX_Request, envp) foreign import ccall unsafe "fcgiapp.h FCGX_InitRequest" fcgx_initrequest :: Ptr FCGX_Request -> CInt -> CInt -> IO CInt foreign import ccall safe "fcgiapp.h FCGX_Accept_r" fcgx_accept_r :: Ptr FCGX_Request -> IO CInt acceptRequest :: IO (Ptr FCGX_Request) acceptRequest = do reqp <- mallocBytes (#size FCGX_Request) initAndAccept reqp return reqp where initAndAccept reqp = do testReturn "FCGX_InitRequest" $ fcgx_initrequest reqp 0 0 testReturn "FCGX_Accept_r" $ fcgx_accept_r reqp withRequest :: (Ptr FCGX_Request -> IO ()) -> IO () withRequest f = do req <- acceptRequest f req `finally` finishRequest req foreign import ccall unsafe "fcgiapp.h FCGX_Finish_r" fcgx_finish_r :: Ptr FCGX_Request -> IO () finishRequest :: Ptr FCGX_Request -> IO () finishRequest reqp = do fcgx_finish_r reqp free reqp handleRequest :: W.Application -> StreamPtr -> StreamPtr -> Environ -> Maybe S.ByteString -- sendfile -> IO () handleRequest f ins outs env xsendfile = do vars <- environToTable env let vars' = map (S8.unpack *** S8.unpack) vars let input = const $ sRead ins let hPut = sPutStr' outs CGI.runGeneric vars' (CGI.requestBodyFunc input) hPut xsendfile f data FCGX_Request -- -- * Stream IO -- sPutStr' :: StreamPtr -> BS.ByteString -> IO () sPutStr' h str = BSB.unsafeUseAsCStringLen str $ fcgxPutCStringLen h fcgxPutCStringLen :: StreamPtr -> CStringLen -> IO () fcgxPutCStringLen h (cs,len) = testReturn "FCGX_PutStr" $ fcgx_putStr cs (fromIntegral len) h sRead :: StreamPtr -> IO (Maybe BS.ByteString) sRead h = buildByteString (fcgxGetBuf h) 4096 fcgxGetBuf :: StreamPtr -> Ptr a -> Int -> IO Int fcgxGetBuf h p c = liftM fromIntegral $ fcgx_getStr (castPtr p) (fromIntegral c) h -- -- * ByteString utilities -- -- | Data.ByteString.Lazy.hGetContentsN generalized to arbitrary -- reading functions. buildByteString :: (Ptr Word8 -> Int -> IO Int) -> Int -> IO (Maybe BS.ByteString) buildByteString f k = do ps <- BSB.createAndTrim k $ \p -> f p k case BS.length ps of 0 -> return Nothing _ -> return $ Just ps -- -- * Utilities -- testReturn :: String -> IO CInt -> IO () testReturn e = throwIfNeg_ (\n -> e ++ " failed with error code: "++ show n) environToTable :: Environ -> IO [(S.ByteString, S.ByteString)] environToTable arr = do css <- peekArray0 nullPtr arr ss <- mapM S.packCString css return $ map splitEq ss where splitEq s = let (a, b) = S.breakByte 61 s in (a, S.drop 1 b)