Remove some tricky handlers

This commit is contained in:
Michael Snoyman 2018-08-20 08:51:39 +03:00
parent 9cf4a6890e
commit e2ce4d7599
No known key found for this signature in database
GPG Key ID: A048E8C057E86876
38 changed files with 10 additions and 862 deletions

View File

@ -53,22 +53,22 @@ matrix:
# addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 7.10.3"
addons: {apt: {packages: [libfcgi-dev,cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.0.2"
addons: {apt: {packages: [libfcgi-dev,cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.2.2"
addons: {apt: {packages: [libfcgi-dev,cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.4.3 CABALVER=2.2 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.4.3"
addons: {apt: {packages: [libfcgi-dev,cabal-install-2.2,ghc-8.4.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
# Build with the newest GHC and cabal-install. This is an accepted failure,
# see below.
- env: BUILD=cabal GHCVER=head CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC HEAD"
addons: {apt: {packages: [libfcgi-dev,cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
# The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
# variable, such as using --stack-yaml to point to a different file.
@ -86,7 +86,7 @@ matrix:
- env: BUILD=stack ARGS="--resolver lts-6" STACK_YAML="stack-lts-6.yaml"
compiler: ": #stack 7.10.3"
addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-7"
# compiler: ": #stack 8.0.1"
@ -94,20 +94,20 @@ matrix:
- env: BUILD=stack ARGS="--resolver lts-9" STACK_YAML="stack-lts-9.yaml"
compiler: ": #stack 8.0.2"
addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
addons: {apt: {packages: [libgmp-dev]}}
- env: BUILD=stack ARGS="--resolver lts-11" STACK_YAML="stack-lts-11.yaml"
compiler: ": #stack 8.2.2"
addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
addons: {apt: {packages: [libgmp-dev]}}
- env: BUILD=stack ARGS="--resolver lts-12" STACK_YAML="stack-lts-12.yaml"
compiler: ": #stack 8.4.3"
addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
addons: {apt: {packages: [libgmp-dev]}}
# Nightly builds are allowed to fail
- env: BUILD=stack ARGS="--resolver nightly" STACK_YAML="stack-nightly.yaml"
compiler: ": #stack nightly"
addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
addons: {apt: {packages: [libgmp-dev]}}
# Build on macOS in addition to Linux
#- env: BUILD=stack ARGS=""
@ -166,11 +166,6 @@ before_install:
if [ `uname` = "Darwin" ]
then
travis_retry curl --insecure -L https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
# brew no longer has fcgi
# brew install fcgi
grep -v wai-handler-fastcgi < $STACK_YAML > tmp
mv tmp $STACK_YAML
else
travis_retry curl -L https://get.haskellstack.org/stable/linux-x86_64.tar.gz | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
fi

View File

@ -7,7 +7,6 @@ packages:
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-websockets
- ./wai-conduit
flags:

View File

@ -7,7 +7,6 @@ packages:
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-websockets
- ./wai-conduit
flags:

View File

@ -7,7 +7,6 @@ packages:
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-websockets
- ./wai-conduit
extra-deps:

View File

@ -7,7 +7,6 @@ packages:
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-websockets
- ./wai-conduit
extra-deps:

View File

@ -7,7 +7,6 @@ packages:
- ./warp
- ./warp-tls
- ./wai-app-static
- ./wai-handler-fastcgi
- ./wai-websockets
- ./wai-conduit
flags:

View File

@ -1,4 +0,0 @@
/dist/
*.swp
*.hi
*.o

View File

@ -1,3 +0,0 @@
## 3.0.0.2
* Support wai 3.2

View File

@ -1,20 +0,0 @@
Copyright (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.

View File

@ -1,192 +0,0 @@
{-# 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 <http://fastcgi.com/>, 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 <fcgiapp.h>
------------------------------------------------------------------------
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)

View File

@ -1,3 +0,0 @@
## wai-handler-fastcgi
Calls out to the libfcgi C library.

View File

@ -1,7 +0,0 @@
#!/usr/bin/env runhaskell
> module Main where
> import Distribution.Simple
> main :: IO ()
> main = defaultMain

View File

@ -1,9 +0,0 @@
#!/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

View File

@ -1,3 +0,0 @@
ghc-options: -optc@CPPFLAGS@
cc-options: @CPPFLAGS@
ld-options: @LDFLAGS@

View File

@ -1,19 +0,0 @@
# Run with lighttpd -D -f lighttpd.conf
server.port = 3000
server.document-root = "."
server.modules = ("mod_fastcgi", "mod_rewrite")
url.rewrite-once = (
"(.*)" => "/app/$1"
)
fastcgi.server = (
"/app" => ((
"socket" => "/tmp/test.fastcgi.socket",
"check-local" => "disable",
"bin-path" => "./test",
"min-procs" => 1,
"max-procs" => 12,
"idle-timeout" => 30
))
)

View File

@ -1,19 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.FastCGI
import Control.Monad.IO.Class
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.Enumerator as E
main = run app
app req
| pathInfo req == "/" = return $ responseLBS status200 [("Content-Type", "text/html")] "<form method='post' action='/post'><input type='text' name='name'><input type='submit'></form>"
app req = do
bss <- E.consume
return $ responseLBS status200 [("Content-Type", "text/plain")] $ L.concat
[ L8.pack $ show $ requestHeaders req
, "\n"
, L.fromChunks bss
]

View File

@ -1,31 +0,0 @@
name: wai-handler-fastcgi
version: 3.0.0.2
license: MIT
license-file: LICENSE
author: Michael Snoyman <michael@snoyman.com>
maintainer: Michael Snoyman <michael@snoyman.com>
synopsis: Wai handler to fastcgi
description: API docs and the README are available at <http://www.stackage.org/package/wai-handler-fastcgi>.
category: Web
stability: stable
cabal-version: >= 1.6
build-type: Configure
extra-source-files: configure fastcgi.buildinfo.in README.md ChangeLog.md
homepage: http://www.yesodweb.com/book/web-application-interface
library
build-depends: base >= 4 && < 5
, wai >= 3.0 && < 3.3
, wai-extra >= 3.0 && < 3.1
, 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

View File

@ -1,2 +0,0 @@
dist/
*.swp

View File

@ -1,35 +0,0 @@
## 3.0.2.4
* Drop dependency on blaze-builder, requiring streaming-commons >= 0.2
## 3.0.2.3
* `process` package bump
## 3.0.2.2
* Improvements to ping's javascript script. [#494](https://github.com/yesodweb/wai/pull/494)
## 3.0.2.1
* Relax upper bound on process
## 3.0.2
* Don't launch if server fails; kill server on exit [#537](https://github.com/yesodweb/wai/issues/537) [#541](https://github.com/yesodweb/wai/pull/541)
## 3.0.1
* make host configurable too (fixes #538) [#539](https://github.com/yesodweb/wai/pull/539)
## 3.0.0.5
* Support wai/warp 3.2
## 3.0.0.3
Allow blaze-builder 0.4
## 3.0.0.2
* Support for Win64

View File

@ -1,20 +0,0 @@
Copyright (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.

View File

@ -1,222 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CPP #-}
module Network.Wai.Handler.Launch
( run
, runUrl
, runUrlPort
, runHostPortUrl
) where
import Network.Wai
import Network.Wai.Internal
import Network.HTTP.Types
import qualified Network.Wai.Handler.Warp as Warp
import Data.IORef
import Data.Monoid (mappend)
import Data.String (fromString)
import Control.Concurrent (forkIO, threadDelay, newEmptyMVar, putMVar, takeMVar)
import Control.Concurrent.Async (race)
import Control.Monad.IO.Class (liftIO)
import Control.Monad (unless)
import Control.Exception (throwIO)
import Data.Function (fix)
import qualified Data.ByteString as S
import Data.ByteString.Builder (Builder, byteString)
import qualified Data.ByteString.Builder.Extra as Builder (flush)
#if WINDOWS
import Foreign
import Foreign.C.String
#else
import System.Process (rawSystem)
#endif
import Data.Streaming.ByteString.Builder as B (newBuilderRecv, defaultStrategy)
import qualified Data.Streaming.Zlib as Z
ping :: IORef Bool -> Middleware
ping active app req sendResponse
| pathInfo req == ["_ping"] = do
liftIO $ writeIORef active True
sendResponse $ responseLBS status200 [] ""
| otherwise = app req $ \res -> do
let isHtml hs =
case lookup "content-type" hs of
Just ct -> "text/html" `S.isPrefixOf` ct
Nothing -> False
if isHtml $ responseHeaders res
then do
let (s, hs, withBody) = responseToStream res
(isEnc, headers') = fixHeaders id hs
headers'' = filter (\(x, _) -> x /= "content-length") headers'
withBody $ \body ->
sendResponse $ responseStream s headers'' $ \sendChunk flush ->
addInsideHead sendChunk flush $ \sendChunk' flush' ->
if isEnc
then decode sendChunk' flush' body
else body sendChunk' flush'
else sendResponse res
decode :: (Builder -> IO ()) -> IO ()
-> StreamingBody
-> IO ()
decode sendInner flushInner streamingBody = do
(blazeRecv, blazeFinish) <- newBuilderRecv defaultStrategy
inflate <- Z.initInflate $ Z.WindowBits 31
let send builder = blazeRecv builder >>= goBuilderPopper
goBuilderPopper popper = fix $ \loop -> do
bs <- popper
unless (S.null bs) $ do
Z.feedInflate inflate bs >>= goZlibPopper
loop
goZlibPopper popper = fix $ \loop -> do
res <- popper
case res of
Z.PRDone -> return ()
Z.PRNext bs -> do
sendInner $ byteString bs
loop
Z.PRError e -> throwIO e
streamingBody send (send Builder.flush)
mbs <- blazeFinish
case mbs of
Nothing -> return ()
Just bs -> Z.feedInflate inflate bs >>= goZlibPopper
Z.finishInflate inflate >>= sendInner . byteString
toInsert :: S.ByteString
toInsert = "<script>setInterval(function(){var x;if(window.XMLHttpRequest){x=new XMLHttpRequest();}else{x=new ActiveXObject(\"Microsoft.XMLHTTP\");}x.open(\"GET\",\"/_ping?\" + (new Date()).getTime(),true);x.send();},60000)</script>"
addInsideHead :: (Builder -> IO ())
-> IO ()
-> StreamingBody
-> IO ()
addInsideHead sendInner flushInner streamingBody = do
(blazeRecv, blazeFinish) <- newBuilderRecv defaultStrategy
ref <- newIORef $ Just (S.empty, whole)
streamingBody (inner blazeRecv ref) (flush blazeRecv ref)
state <- readIORef ref
mbs <- blazeFinish
held <- case mbs of
Nothing -> return state
Just bs -> push state bs
case state of
Nothing -> return ()
Just (held, _) -> sendInner $ byteString held `mappend` byteString toInsert
where
whole = "<head>"
flush blazeRecv ref = inner blazeRecv ref Builder.flush
inner blazeRecv ref builder = do
state0 <- readIORef ref
popper <- blazeRecv builder
let loop state = do
bs <- popper
if S.null bs
then writeIORef ref state
else push state bs >>= loop
loop state0
push Nothing x = sendInner (byteString x) >> return Nothing
push (Just (held, atFront)) x
| atFront `S.isPrefixOf` x = do
let y = S.drop (S.length atFront) x
sendInner $ byteString held
`mappend` byteString atFront
`mappend` byteString toInsert
`mappend` byteString y
return Nothing
| whole `S.isInfixOf` x = do
let (before, rest) = S.breakSubstring whole x
let after = S.drop (S.length whole) rest
sendInner $ byteString held
`mappend` byteString before
`mappend` byteString whole
`mappend` byteString toInsert
`mappend` byteString after
return Nothing
| x `S.isPrefixOf` atFront = do
let held' = held `S.append` x
atFront' = S.drop (S.length x) atFront
return $ Just (held', atFront')
| otherwise = do
let (held', atFront', x') = getOverlap whole x
sendInner $ byteString held `mappend` byteString x'
return $ Just (held', atFront')
getOverlap :: S.ByteString -> S.ByteString -> (S.ByteString, S.ByteString, S.ByteString)
getOverlap whole x =
go whole
where
go piece
| S.null piece = ("", whole, x)
| piece `S.isSuffixOf` x =
let x' = S.take (S.length x - S.length piece) x
atFront = S.drop (S.length piece) whole
in (piece, atFront, x')
| otherwise = go $ S.init piece
fixHeaders :: ([Header] -> [Header])
-> [Header]
-> (Bool, [Header])
fixHeaders front [] = (False, front [])
fixHeaders front (("content-encoding", "gzip"):rest) = (True, front rest)
fixHeaders front (x:xs) = fixHeaders (front . (:) x) xs
#if WINDOWS
foreign import ccall "launch"
launch' :: Int -> CString -> IO ()
#endif
launch :: Int -> String -> IO ()
#if WINDOWS
launch port s = withCString s $ launch' port
#else
launch port s = forkIO (rawSystem
#if MAC
"open"
#else
"xdg-open"
#endif
["http://127.0.0.1:" ++ show port ++ "/" ++ s] >> return ()) >> return ()
#endif
run :: Application -> IO ()
run = runUrl ""
runUrl :: String -> Application -> IO ()
runUrl = runUrlPort 4587
runUrlPort :: Int -> String -> Application -> IO ()
runUrlPort = runHostPortUrl "*4"
-- |
--
-- @since 3.0.1
runHostPortUrl :: String -> Int -> String -> Application -> IO ()
runHostPortUrl host port url app = do
ready <- newEmptyMVar
active <- newIORef True
let settings =
Warp.setPort port $
Warp.setOnException (\_ _ -> return ()) $
Warp.setHost (fromString host) $
Warp.setBeforeMainLoop (putMVar ready ()) $
Warp.defaultSettings
-- Run these threads concurrently; when either one terminates or
-- raises an exception, the same happens to the other.
fmap (either id id) $ race
-- serve app, keep updating the activity flag
(Warp.runSettings settings (ping active app))
-- wait for server startup, launch browser, poll until server idle
(takeMVar ready >> launch port url >> loop active)
loop :: IORef Bool -> IO ()
loop active = do
let seconds = 120
threadDelay $ 1000000 * seconds
b <- readIORef active
if b
then writeIORef active False >> loop active
else return ()

View File

@ -1,4 +0,0 @@
## wai-handler-launch
This handles cross-platform launching and inserts Javascript code to ping the
server. When the server no longer receives pings, it shuts down.

View File

@ -1,7 +0,0 @@
#!/usr/bin/env runhaskell
> module Main where
> import Distribution.Simple
> main :: IO ()
> main = defaultMain

View File

@ -1,22 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai.Handler.Launch (insideHead)
import Test.Hspec
import Test.Hspec.HUnit
import Data.Enumerator hiding (map)
import Test.HUnit
import qualified Data.ByteString as S
main :: IO ()
main = hspec $ describe "insideHead"
[ it "handles single chunks" $ helper "bar<head>foobaz" ["bar<head>baz"]
, it "handles single chunks, no <head>" $ helper "barfoo" ["bar"]
, it "handles whole chunks" $ helper "bar<head>foobaz" ["bar", "<head>", "baz"]
, it "handles split chunks" $ helper "bar<head>foobaz" ["bar", "<he", "ad>", "baz"]
, it "handles many chunks" $ helper "bar<head>foobaz1234567890" ["bar", "<he", "ad>", "baz", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
, it "handles many pieces" $ helper "bar<head>foobaz" $ map S.singleton $ S.unpack "bar<head>baz"
]
helper :: S.ByteString -> [S.ByteString] -> Assertion
helper res pieces = do
x <- run_ $ enumList 1 pieces $$ joinI $ insideHead "foo" $$ consume
S.concat x @?= res

View File

@ -1,7 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Launch
import Network.Wai.Middleware.Gzip
main = runUrl "FIXME" $ gzip def $ \_ f -> f $ responseLBS status200 [("Content-Type", "text/html; charset=utf8")] "<html><head></head><body>HELLO THERE"

View File

@ -1,36 +0,0 @@
Name: wai-handler-launch
Version: 3.0.2.4
Synopsis: Launch a web app in the default browser.
description: API docs and the README are available at <http://www.stackage.org/package/wai-handler-launch>.
License: MIT
License-file: LICENSE
Author: Michael Snoyman
Maintainer: michael@snoyman.com
Category: Web
Build-type: Simple
Cabal-version: >=1.6
extra-source-files: README.md ChangeLog.md
Library
Exposed-modules: Network.Wai.Handler.Launch
build-depends: base >= 4 && < 5
, wai >= 3.0 && < 3.3
, warp >= 3.0 && < 3.3
, http-types >= 0.7
, transformers >= 0.2.2
, bytestring >= 0.10.4
, streaming-commons >= 0.2
, async
if os(windows)
c-sources: windows.c
cpp-options: -DWINDOWS
extra-libraries: Shell32 msvcrt
else
build-depends: process >= 1.0 && < 1.7
if os(darwin)
cpp-options: -DMAC
source-repository head
type: git
location: git://github.com/yesodweb/wai.git

View File

@ -1,12 +0,0 @@
#include <windows.h>
#include <shellapi.h>
#include <stdio.h>
void launch(int port, char *s)
{
int len = 8 + strlen("http://127.0.0.1:") + strlen(s);
char *buff = malloc(len);
_snprintf(buff, len, "http://127.0.0.1:%d/%s", port, s);
ShellExecute(NULL, "open", buff, NULL, NULL, SW_SHOWNORMAL);
free(buff);
}

View File

@ -1,2 +0,0 @@
dist
*.swp

View File

@ -1,3 +0,0 @@
## 3.0.0.3
* Support for wai/warp 3.2

View File

@ -1,20 +0,0 @@
Copyright (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.

View File

@ -1,21 +0,0 @@
{-# LANGUAGE ForeignFunctionInterface #-}
module Network.Wai.Handler.Webkit (run) where
import Network.Wai (Application)
import qualified Network.Wai.Handler.Warp as S
import Control.Concurrent (forkOS)
import Control.Concurrent.MVar
import Foreign.C.String (CString, withCString)
import Control.Exception (finally)
run :: String -- ^ Title to show in titlebar
-> Application -> IO ()
run title app = do
mvar <- newEmptyMVar
_ <- forkOS $ finally (S.run 3000 app) (putMVar mvar ())
_ <- forkOS $ finally (withCString title startBrowser) (putMVar mvar ())
_ <- takeMVar mvar
return ()
foreign import ccall "start_browser"
startBrowser :: CString -> IO ()

View File

@ -1,53 +0,0 @@
wai-handler-webkit
==================
Turn WAI applications into standalone GUIs using Qt WebKit.
Linux
-----
You'll need the appropriate system libraries, on Ubuntu:
apt-get install libqtwebkit-dev
On Lucid, this required adding a PPA:
sudo add-apt-repository ppa:kubuntu-ppa/backports
Windows
-------
Install the Qt SDK from <http://qt.nokia.com/downloads/>
Your application's Cabal file will require certain options for Windows,
shown below. In particular, we need to link with `g++`, so make sure
it's in your `PATH`. The option `-optl-mwindows` ensures that the
application does not open a terminal.
if os(windows)
ghc-options: -Wall -threaded -pgml g++ -optl-static -optl-mwindows
else
ghc-options: -Wall
Run `cabal-install` with the Qt `include` and `lib` directories.
export QT_PATH=c:/QtSDK/Desktop/Qt/4.7.3/mingw
cabal-dev install \
--extra-include-dirs=$QT_PATH/include \
--extra-include-dirs=$QT_PATH/include/QtCore \
--extra-include-dirs=$QT_PATH/include/QtNetwork \
--extra-include-dirs=$QT_PATH/include/QtGui \
--extra-include-dirs=$QT_PATH/include/QtWebKit \
--extra-lib-dirs=$QT_PATH/lib
You'll need to include these DLLs with your application:
phonon4.dll
libgcc_s_dw2-1.dll
QtCore4.dll
QtGui4.dll
QtNetwork4.dll
QtWebKit4.dll

View File

@ -1,7 +0,0 @@
#!/usr/bin/env runhaskell
> module Main where
> import Distribution.Simple
> main :: IO ()
> main = defaultMain

View File

@ -1,10 +0,0 @@
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Webkit
import Network.HTTP.Types
main :: IO ()
main = run "Sample App" app
app :: Application
app _ response = response $ responseLBS status200 [("Content-Type", "text/html")] "<h1>Hello World!</h1>"

View File

@ -1,30 +0,0 @@
name: wai-handler-webkit
version: 3.0.0.3
license: MIT
license-file: LICENSE
author: Michael Snoyman <michael@snoyman.com>
maintainer: Michael Snoyman <michael@snoyman.com>
synopsis: Turn WAI applications into standalone GUIs using QtWebkit.
description: API docs and the README are available at <http://www.stackage.org/package/wai-handler-webkit>.
category: Web
stability: unstable
cabal-version: >= 1.6
build-type: Simple
homepage: https://github.com/yesodweb/wai/tree/master/wai-handler-webkit
extra-source-files: README.md ChangeLog.md
library
build-depends: base >= 4 && < 5
, wai >= 3.0 && < 3.3
, warp >= 3.0 && < 3.3
ghc-options: -Wall
exposed-modules: Network.Wai.Handler.Webkit
c-sources: webkit.cpp
if os(windows)
extra-libraries: QtCore4, QtGui4, QtNetwork4, QtWebKit4
else
pkgconfig-depends: QtWebKit
source-repository head
type: git
location: git://github.com/yesodweb/wai.git

View File

@ -1,19 +0,0 @@
#include <QApplication>
#include <QPushButton>
#include <QtWebKit>
extern "C" {
int start_browser(char *title)
{
char *argv[1];
argv[0] = title;
int argc = 1;
QApplication app(argc, argv);
QWebView *view = new QWebView();
view->load(QUrl("http://localhost:3000/"));
view->show();
return app.exec();
}
}