1
0
forked from GitHub/gf-core

pgf service: added a hook for external services

This is really reinventing CGI, people should learn how to write CGI scripts
instead...
TODO: better handling of temporary files
This commit is contained in:
hallgren
2011-08-22 15:34:44 +00:00
parent 36b9d55ed6
commit d8d80693db
2 changed files with 43 additions and 6 deletions

View File

@@ -1,10 +1,11 @@
{-# LANGUAGE DeriveDataTypeable, CPP #-} {-# LANGUAGE DeriveDataTypeable, CPP #-}
module FastCGIUtils (--initFastCGI, loopFastCGI, module FastCGIUtils (--initFastCGI, loopFastCGI,
throwCGIError, handleCGIErrors, throwCGIError, handleCGIErrors,
stderrToFile, stderrToFile,logError,
outputJSONP, outputJSONP,outputEncodedJSONP,
outputPNG, outputPNG,
outputHTML, outputHTML,
outputPlain,
splitBy) where splitBy) where
import Control.Concurrent import Control.Concurrent
@@ -160,11 +161,14 @@ handleCGIErrors x = x `catchCGI` \e -> case fromException e of
-- * General CGI and JSON stuff -- * General CGI and JSON stuff
outputJSONP :: JSON a => a -> CGI CGIResult outputJSONP :: JSON a => a -> CGI CGIResult
outputJSONP x = outputJSONP = outputEncodedJSONP . encode
outputEncodedJSONP :: String -> CGI CGIResult
outputEncodedJSONP json =
do mc <- getInput "jsonp" do mc <- getInput "jsonp"
let str = case mc of let str = case mc of
Nothing -> encode x Nothing -> json
Just c -> c ++ "(" ++ encode x ++ ")" Just c -> c ++ "(" ++ json ++ ")"
setHeader "Content-Type" "text/javascript; charset=utf-8" setHeader "Content-Type" "text/javascript; charset=utf-8"
outputStrict $ UTF8.encodeString str outputStrict $ UTF8.encodeString str
@@ -178,6 +182,11 @@ outputHTML x = do
setHeader "Content-Type" "text/html" setHeader "Content-Type" "text/html"
outputStrict $ UTF8.encodeString x outputStrict $ UTF8.encodeString x
outputPlain :: String -> CGI CGIResult
outputPlain x = do
setHeader "Content-Type" "text/plain"
outputStrict $ UTF8.encodeString x
outputStrict :: String -> CGI CGIResult outputStrict :: String -> CGI CGIResult
outputStrict x | x == x = output x outputStrict x | x == x = output x
| otherwise = fail "I am the pope." | otherwise = fail "I am the pope."

View File

@@ -16,7 +16,7 @@ import qualified Codec.Binary.UTF8.String as UTF8 (decodeString)
import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Lazy as BS
import Control.Concurrent import Control.Concurrent
import Control.Exception import Control.Exception(evaluate)
import Control.Monad import Control.Monad
import Data.Char import Data.Char
import Data.Function (on) import Data.Function (on)
@@ -27,6 +27,7 @@ import System.Random
import System.Process import System.Process
import System.Exit import System.Exit
import System.IO import System.IO
import System.Directory(removeFile)
logFile :: FilePath logFile :: FilePath
logFile = "pgf-error.log" logFile = "pgf-error.log"
@@ -65,6 +66,9 @@ pgfMain pgf command = do
"parsetree" -> getTree >>= \t -> getFrom >>= \(Just l) -> liftIO (doGraphvizParseTree pgf l t) >>= outputPNG "parsetree" -> getTree >>= \t -> getFrom >>= \(Just l) -> liftIO (doGraphvizParseTree pgf l t) >>= outputPNG
"alignment" -> getTree >>= liftIO . doGraphvizAlignment pgf >>= outputPNG "alignment" -> getTree >>= liftIO . doGraphvizAlignment pgf >>= outputPNG
"browse" -> outputHTML =<< doBrowse pgf `fmap` getId `ap` getCSSClass `ap` getHRef "browse" -> outputHTML =<< doBrowse pgf `fmap` getId `ap` getCSSClass `ap` getHRef
"external" -> do cmd <- getInput "external"
input <- getText
doExternal cmd input
_ -> throwCGIError 400 "Unknown command" ["Unknown command: " ++ show command] _ -> throwCGIError 400 "Unknown command" ["Unknown command: " ++ show command]
where where
getText :: CGI String getText :: CGI String
@@ -127,6 +131,30 @@ pgfMain pgf command = do
Just lang | lang `elem` PGF.languages pgf -> return $ Just lang Just lang | lang `elem` PGF.languages pgf -> return $ Just lang
| otherwise -> throwCGIError 400 "Unknown language" ["Unknown language: " ++ l] | otherwise -> throwCGIError 400 "Unknown language" ["Unknown language: " ++ l]
-- Hook for simple extensions of the PGF service
doExternal Nothing input = throwCGIError 400 "Unknown external command" ["Unknown external command"]
doExternal (Just cmd) input =
do liftIO $ logError ("External command: "++cmd)
cmds <- liftIO $ (readIO =<< readFile "external_services")
`catch` const (return [])
liftIO $ logError ("External services: "++show cmds)
maybe err ok (lookup cmd cmds)
where
err = throwCGIError 400 "Unknown external command" ["Unknown external command: "++cmd]
ok output_type =
do let tmpfile1 = "external_input.txt"
tmpfile2 = "external_output.txt"
liftIO $ writeFile "external_input.txt" input
liftIO $ system $ cmd ++ " " ++ tmpfile1 ++ " > " ++ tmpfile2
liftIO $ removeFile tmpfile1
r <- case output_type of
"jsonp" -> outputEncodedJSONP =<< liftIO (readFile tmpfile2)
"image/png" -> outputPNG =<< liftIO (BS.readFile tmpfile2)
"text/html" -> outputHTML =<< liftIO (readFile tmpfile2)
_ -> outputPlain =<< liftIO (readFile tmpfile2)
liftIO $ removeFile tmpfile2
return r
doTranslate :: PGF -> String -> Maybe PGF.Type -> Maybe PGF.Language -> Maybe PGF.Language -> JSValue doTranslate :: PGF -> String -> Maybe PGF.Type -> Maybe PGF.Language -> Maybe PGF.Language -> JSValue
doTranslate pgf input mcat mfrom mto = doTranslate pgf input mcat mfrom mto =
showJSON showJSON