RUN_COMMAND = $(MAKE) -C examples run
CONFIGURE_ARGS = -O
+#CONFIGURE_ARGS = -O -fssl
include cabal-package.mk
Description: Build the lucu-implant-file program.
Default: True
+Flag ssl
+ Description: Enable SSL support.
+ Default: False
+
Library
Build-Depends:
- HsOpenSSL == 0.10.*,
ascii == 0.0.*,
attoparsec == 0.9.*,
base == 4.*,
time-http == 0.2.*,
transformers == 0.2.*
+ if flag(ssl)
+ Build-Depends:
+ HsOpenSSL == 0.10.*
+ CPP-Options:
+ -DHAVE_SSL
+
Exposed-Modules:
Network.HTTP.Lucu
Network.HTTP.Lucu.Abortion
-- chunked I\/O, ETag comparison and \"100 Continue\".
--
-- [/SSL connections/] Lucu can handle HTTP connections over Secure
--- Socket Layer.
+-- Socket Layer when configured with -fssl flag.
--
-- Lucu is not a replacement for Apache or lighttpd. It is intended to
-- be used to build an efficient web-based RESTful application which
{-# LANGUAGE
- OverloadedStrings
+ CPP
+ , OverloadedStrings
, UnicodeSyntax
#-}
-- |Configurations for the Lucu httpd.
module Network.HTTP.Lucu.Config
( Config(..)
+#if defined(HAVE_SSL)
, SSLConfig(..)
+#endif
, defaultConfig
)
where
import Network.BSD
import Network.HTTP.Lucu.MIMEType.Guess
import Network.HTTP.Lucu.MIMEType.DefaultExtensionMap
+#if defined(HAVE_SSL)
import OpenSSL.Session
+#endif
import System.IO.Unsafe
-- |Configuration record for to run the httpd.
-- problem.)
, cnfServerV6Addr ∷ !(Maybe HostName)
+#if defined(HAVE_SSL)
-- |Configuration for HTTPS connections. Set this 'Nothing' to
-- disable HTTPS.
, cnfSSLConfig ∷ !(Maybe SSLConfig)
+#endif
-- |The maximum number of requests to simultaneously accept in one
-- connection. If a client exceeds this limitation, its last
, cnfExtToMIMEType ∷ !ExtMap
}
+#if defined(HAVE_SSL)
-- |Configuration record for HTTPS connections.
data SSLConfig
= SSLConfig {
-- up yourself with at least a server certification.
, sslContext ∷ !SSLContext
}
+#endif
-- |The default configuration. Generally you can use this value as-is,
-- or possibly you just want to replace the 'cnfServerSoftware' and
, cnfServerPort = "http"
, cnfServerV4Addr = Just "0.0.0.0"
, cnfServerV6Addr = Just "::"
+#if defined(HAVE_SSL)
, cnfSSLConfig = Nothing
+#endif
, cnfMaxPipelineDepth = 100
, cnfMaxEntityLength = 16 * 1024 * 1024 -- 16 MiB
, cnfDumpTooLateAbortionToStderr = True
{-# LANGUAGE
- DoAndIfThenElse
+ CPP
+ , DoAndIfThenElse
, UnicodeSyntax
#-}
-- |Type class for things behaves like a 'I.Handle'.
import qualified Blaze.ByteString.Builder as BB
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy.Char8 as L
+#if defined(HAVE_SSL)
import qualified OpenSSL.Session as SSL
import OpenSSL.X509
+#endif
import Prelude.Unicode
import qualified System.IO as I
hGetBS ∷ h → Int → IO B.ByteString
hPutBS ∷ h → B.ByteString → IO ()
+#if defined(HAVE_SSL)
hGetPeerCert ∷ h → IO (Maybe X509)
hGetPeerCert = const $ return Nothing
+#endif
hFlush ∷ h → IO ()
hClose ∷ h → IO ()
hFlush = I.hFlush
hClose = I.hClose
+#if defined(HAVE_SSL)
instance HandleLike SSL.SSL where
hGetLBS = SSL.lazyRead
hFlush _ = return () -- No need to do anything.
hClose s = SSL.shutdown s SSL.Bidirectional
+#endif
hPutBuilder ∷ HandleLike h ⇒ h → Builder → IO ()
{-# INLINE hPutBuilder #-}
{-# LANGUAGE
- UnicodeSyntax
+ CPP
+ , UnicodeSyntax
#-}
-- |The entry point of Lucu httpd.
module Network.HTTP.Lucu.Httpd
= withSocketsDo $
do let launchers
= catMaybes
- [ do scnf ← cnfSSLConfig cnf
+ [ do addr ← cnfServerV4Addr cnf
+ return ( launchListener =≪ listenOn AF_INET addr (cnfServerPort cnf)
+ )
+ , do addr ← cnfServerV6Addr cnf
+ return ( launchListener =≪ listenOn AF_INET6 addr (cnfServerPort cnf)
+ )
+#if defined(HAVE_SSL)
+ , do scnf ← cnfSSLConfig cnf
addr ← cnfServerV4Addr cnf
return ( do so ← listenOn AF_INET addr (sslServerPort scnf)
launchListener (sslContext scnf, so)
return ( do so ← listenOn AF_INET6 addr (sslServerPort scnf)
launchListener (sslContext scnf, so)
)
- , do addr ← cnfServerV4Addr cnf
- return ( launchListener =≪ listenOn AF_INET addr (cnfServerPort cnf)
- )
- , do addr ← cnfServerV6Addr cnf
- return ( launchListener =≪ listenOn AF_INET6 addr (cnfServerPort cnf)
- )
+#endif
]
sequence_ launchers
waitForever
{-# LANGUAGE
- DeriveDataTypeable
+ CPP
+ , DeriveDataTypeable
, ExistentialQuantification
, OverloadedStrings
, RecordWildCards
import Network.HTTP.Lucu.Preprocess
import Network.HTTP.Lucu.Request
import Network.HTTP.Lucu.Response
+#if defined(HAVE_SSL)
import OpenSSL.X509
+#endif
class Typeable i ⇒ Interaction i where
toInteraction ∷ i → SomeInteraction
= NI {
niConfig ∷ !Config
, niRemoteAddr ∷ !SockAddr
+#if defined(HAVE_SSL)
, niRemoteCert ∷ !(Maybe X509)
+#endif
, niRequest ∷ !Request
, niResourcePath ∷ ![Strict.ByteString]
, niExpectedContinue ∷ !Bool
mkNormalInteraction ∷ Config
→ SockAddr
+#if defined(HAVE_SSL)
→ Maybe X509
+#endif
→ AugmentedRequest
→ [Strict.ByteString]
→ IO NormalInteraction
+#if defined(HAVE_SSL)
mkNormalInteraction config remoteAddr remoteCert (AugmentedRequest {..}) rsrcPath
+#else
+mkNormalInteraction config remoteAddr (AugmentedRequest {..}) rsrcPath
+#endif
= do receiveBodyReq ← newEmptyTMVarIO
receivedBody ← newEmptyTMVarIO
return NI {
niConfig = config
, niRemoteAddr = remoteAddr
+#if defined(HAVE_SSL)
, niRemoteCert = remoteCert
+#endif
, niRequest = arRequest
, niResourcePath = rsrcPath
, niExpectedContinue = arExpectedContinue
{-# LANGUAGE
- DoAndIfThenElse
+ CPP
+ , DoAndIfThenElse
, OverloadedStrings
, RecordWildCards
, ScopedTypeVariables
→ ResourceDef
→ IO ()
acceptRequestForResource ctx@(Context {..}) ar@(AugmentedRequest {..}) input rsrcPath rsrcDef
- = do cert ← hGetPeerCert cHandle
+ = do
+#if defined(HAVE_SSL)
+ cert ← hGetPeerCert cHandle
ni ← mkNormalInteraction cConfig cAddr cert ar rsrcPath
+#else
+ ni ← mkNormalInteraction cConfig cAddr ar rsrcPath
+#endif
tid ← spawnResource rsrcDef ni
enqueue ctx ni
if reqMustHaveBody arRequest then
{-# LANGUAGE
- BangPatterns
+ CPP
+ , BangPatterns
, GeneralizedNewtypeDeriving
, DoAndIfThenElse
, OverloadedStrings
, getRemoteAddr
, getRemoteAddr'
, getRemoteHost
+#if defined(HAVE_SSL)
, getRemoteCertificate
+#endif
, getRequest
, getMethod
, getRequestURI
{-# LANGUAGE
- DoAndIfThenElse
+ CPP
+ , DoAndIfThenElse
, GeneralizedNewtypeDeriving
, OverloadedStrings
, RecordWildCards
, getConfig
, getRemoteAddr
+#if defined(HAVE_SSL)
, getRemoteCertificate
+#endif
, getRequest
, getResourcePath
import Network.HTTP.Lucu.Request
import Network.HTTP.Lucu.Response
import Network.Socket
+#if defined(HAVE_SSL)
import OpenSSL.X509
+#endif
import Prelude hiding (catch)
import Prelude.Unicode
import System.IO
getRemoteAddr ∷ Resource SockAddr
getRemoteAddr = niRemoteAddr <$> getInteraction
+#if defined(HAVE_SSL)
-- | Return the X.509 certificate of the client, or 'Nothing' if:
--
-- * This request didn't came through an SSL stream.
-- 'OpenSSL.Session.VerifyPeer'.
getRemoteCertificate ∷ Resource (Maybe X509)
getRemoteCertificate = niRemoteCert <$> getInteraction
+#endif
-- |Return the 'Request' value representing the request header. You
-- usually don't need to call this function directly.
{-# LANGUAGE
- FlexibleContexts
+ CPP
+ , FlexibleContexts
, FlexibleInstances
, TypeFamilies
, UnicodeSyntax
where
import qualified Network.Socket as So
import Network.HTTP.Lucu.HandleLike
+#if defined(HAVE_SSL)
import qualified OpenSSL.Session as SSL
import Prelude.Unicode
+#endif
import qualified System.IO as I
class (HandleLike (Handle s)) ⇒ SocketLike s where
socketPort = So.socketPort
+#if defined(HAVE_SSL)
instance SocketLike (SSL.SSLContext, So.Socket) where
type Handle (SSL.SSLContext, So.Socket) = SSL.SSL
return (ssl, addr)
socketPort = So.socketPort ∘ snd
+#endif
component: Lucu
release: Lucu-1.0
reporter: PHO <pho@cielonegro.org>
-status: :unstarted
-disposition:
+status: :closed
+disposition: :fixed
creation_time: 2011-10-26 23:04:33.719311 Z
references: []
- PHO <pho@cielonegro.org>
- edited title
- Should be defaulted to off!
+- - 2011-11-12 16:13:20.813907 Z
+ - PHO <pho@cielonegro.org>
+ - closed with disposition fixed
+ - Done.
git_branch:
build: $(TARGETS)
+SSL: SSL.hs
+ -ghc -Wall --make $@ -threaded -O3 -idist -odir dist -hidir dist
+
%: %.hs
ghc -Wall --make $@ -threaded -O3 -idist -odir dist -hidir dist