Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aae14479d | ||
|
|
d021511bd6 | ||
|
|
f943b50a20 | ||
|
|
8c50721309 | ||
|
|
7addd8982f | ||
|
|
d1f26115f6 |
@@ -32,6 +32,7 @@ library
|
|||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
base >=4.7 && <5
|
||||||
, bytestring >=0.10.12.0 && <0.11
|
, bytestring >=0.10.12.0 && <0.11
|
||||||
|
, network
|
||||||
, tcp-streams >=1.0.1.1 && <1.1
|
, tcp-streams >=1.0.1.1 && <1.1
|
||||||
, text >=1.2.4.1 && <1.3
|
, text >=1.2.4.1 && <1.3
|
||||||
, tls
|
, tls
|
||||||
@@ -53,6 +54,7 @@ test-suite gemserv-test
|
|||||||
, bytestring >=0.10.12.0 && <0.11
|
, bytestring >=0.10.12.0 && <0.11
|
||||||
, gemserv
|
, gemserv
|
||||||
, hspec >=2.7.10 && <2.8
|
, hspec >=2.7.10 && <2.8
|
||||||
|
, network
|
||||||
, tcp-streams >=1.0.1.1 && <1.1
|
, tcp-streams >=1.0.1.1 && <1.1
|
||||||
, text >=1.2.4.1 && <1.3
|
, text >=1.2.4.1 && <1.3
|
||||||
, tls
|
, tls
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ dependencies:
|
|||||||
- bytestring >= 0.10.12.0 && < 0.11
|
- bytestring >= 0.10.12.0 && < 0.11
|
||||||
- tcp-streams >= 1.0.1.1 && < 1.1
|
- tcp-streams >= 1.0.1.1 && < 1.1
|
||||||
- text >= 1.2.4.1 && < 1.3
|
- text >= 1.2.4.1 && < 1.3
|
||||||
|
- network
|
||||||
- tls
|
- tls
|
||||||
- x509
|
- x509
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ License along with this program. If not, see
|
|||||||
{-# LANGUAGE LambdaCase, OverloadedStrings, RecordWildCards #-}
|
{-# LANGUAGE LambdaCase, OverloadedStrings, RecordWildCards #-}
|
||||||
|
|
||||||
module Network.GemServ (
|
module Network.GemServ (
|
||||||
|
runGemServer,
|
||||||
encodeGemURL,
|
encodeGemURL,
|
||||||
decodeGemURL,
|
decodeGemURL,
|
||||||
escapeString,
|
escapeString,
|
||||||
unescapeString
|
unescapeString
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Exception.Base (bracket)
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.ByteString.Builder (charUtf8, stringUtf8, toLazyByteString)
|
import Data.ByteString.Builder (charUtf8, stringUtf8, toLazyByteString)
|
||||||
import qualified Data.ByteString.Lazy as BSL
|
import qualified Data.ByteString.Lazy as BSL
|
||||||
@@ -41,9 +43,26 @@ import Data.List (find, intercalate)
|
|||||||
import Data.Maybe (fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Text.Encoding (decodeUtf8')
|
import Data.Text.Encoding (decodeUtf8')
|
||||||
|
import Network.Socket (close)
|
||||||
|
import System.IO.Streams.TCP (bindAndListen)
|
||||||
|
|
||||||
import Network.GemServ.Types
|
import Network.GemServ.Types
|
||||||
|
|
||||||
|
-- | Builds and runs a Gemini server
|
||||||
|
runGemServer
|
||||||
|
:: GemServSettings
|
||||||
|
-- ^ The server settings
|
||||||
|
-> GemHandler
|
||||||
|
-- ^ The handler
|
||||||
|
-> IO ()
|
||||||
|
runGemServer settings _ = bracket
|
||||||
|
( bindAndListen
|
||||||
|
(servConnections settings)
|
||||||
|
(fromIntegral $ servPort settings)
|
||||||
|
)
|
||||||
|
close
|
||||||
|
undefined
|
||||||
|
|
||||||
-- | Encodes a 'GemURL' into a 'String'
|
-- | Encodes a 'GemURL' into a 'String'
|
||||||
encodeGemURL :: GemURL -> String
|
encodeGemURL :: GemURL -> String
|
||||||
encodeGemURL url =
|
encodeGemURL url =
|
||||||
|
|||||||
@@ -25,11 +25,22 @@ License along with this program. If not, see
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
module Network.GemServ.Types (
|
module Network.GemServ.Types (
|
||||||
|
-- * Types
|
||||||
GemURL (..),
|
GemURL (..),
|
||||||
newGemURL
|
GemRequest (..),
|
||||||
|
GemResponse (..),
|
||||||
|
GemHandler,
|
||||||
|
GemServSettings (..),
|
||||||
|
-- * Constructors
|
||||||
|
newGemURL,
|
||||||
|
newGemRequest,
|
||||||
|
newGemResponse,
|
||||||
|
newGemServSettings
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Word (Word32)
|
import qualified Data.ByteString as BS
|
||||||
|
import Data.Word (Word8, Word16, Word32)
|
||||||
|
import Data.X509 (Certificate)
|
||||||
|
|
||||||
-- | Gemini URL
|
-- | Gemini URL
|
||||||
data GemURL = GemURL
|
data GemURL = GemURL
|
||||||
@@ -43,6 +54,41 @@ data GemURL = GemURL
|
|||||||
-- ^ The decoded request query (if supplied)
|
-- ^ The decoded request query (if supplied)
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
|
-- | Describes a Gemini request
|
||||||
|
data GemRequest = GemRequest
|
||||||
|
{ reqURL :: GemURL
|
||||||
|
-- ^ The URL being requested
|
||||||
|
, reqCert :: Maybe Certificate
|
||||||
|
-- ^ The client certificate (if available)
|
||||||
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
|
-- | Describes a response to a Gemini request
|
||||||
|
data GemResponse = GemResponse
|
||||||
|
{ respStatus :: Word8
|
||||||
|
-- ^ The response status code
|
||||||
|
, respMeta :: String
|
||||||
|
-- ^ The response metadata
|
||||||
|
, respBody :: Maybe BS.ByteString
|
||||||
|
-- ^ The response body
|
||||||
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
|
-- | Handles a 'GemRequest' to produce a 'GemResponse'
|
||||||
|
type GemHandler = GemRequest -> IO GemResponse
|
||||||
|
|
||||||
|
-- | The settings required to set up a Gemini server
|
||||||
|
data GemServSettings = GemServSettings
|
||||||
|
{ servConnections :: Int
|
||||||
|
-- ^ Number of simultaneous connections allowed
|
||||||
|
, servPort :: Word16
|
||||||
|
-- ^ The server port number
|
||||||
|
, servCert :: FilePath
|
||||||
|
-- ^ The path to the server certificate
|
||||||
|
, servCertChain :: [FilePath]
|
||||||
|
-- ^ The paths to the chain certificates
|
||||||
|
, servKey :: FilePath
|
||||||
|
-- ^ The path to the private key
|
||||||
|
} deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Builds a new 'GemURL'
|
-- | Builds a new 'GemURL'
|
||||||
newGemURL
|
newGemURL
|
||||||
:: String
|
:: String
|
||||||
@@ -55,4 +101,39 @@ newGemURL host = GemURL
|
|||||||
, gemQuery = Nothing
|
, gemQuery = Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Builds a 'GemRequest'
|
||||||
|
newGemRequest
|
||||||
|
:: GemURL
|
||||||
|
-- ^ The request URL
|
||||||
|
-> GemRequest
|
||||||
|
newGemRequest url = GemRequest
|
||||||
|
{ reqURL = url
|
||||||
|
, reqCert = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Builds a 'GemResponse'
|
||||||
|
newGemResponse :: GemResponse
|
||||||
|
newGemResponse = GemResponse
|
||||||
|
{ respStatus = 20
|
||||||
|
, respMeta = "text/gemini"
|
||||||
|
, respBody = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Builds a reasonable set of server settings.
|
||||||
|
newGemServSettings
|
||||||
|
:: FilePath
|
||||||
|
-- ^ Path to the server certificate
|
||||||
|
-> [FilePath]
|
||||||
|
-- ^ Path to the chain certificates
|
||||||
|
-> FilePath
|
||||||
|
-- ^ Path to the private key
|
||||||
|
-> GemServSettings
|
||||||
|
newGemServSettings cert chain key = GemServSettings
|
||||||
|
{ servConnections = 100
|
||||||
|
, servPort = 1965
|
||||||
|
, servCert = cert
|
||||||
|
, servCertChain = chain
|
||||||
|
, servKey = key
|
||||||
|
}
|
||||||
|
|
||||||
--jl
|
--jl
|
||||||
|
|||||||
Reference in New Issue
Block a user