Adds TLS support
This commit is contained in:
parent
72009b5db2
commit
0c1345b877
19
README.md
19
README.md
@ -1,20 +1,19 @@
|
||||
# hastatic
|
||||
|
||||
[](https://hub.docker.com/r/abhin4v/hastatic/)
|
||||

|
||||
[](https://hub.docker.com/r/abhin4v/hastatic/)  
|
||||
|
||||
_hastatic_ is a tiny static web server for Docker.
|
||||
|
||||
## Features
|
||||
|
||||
- A tiny web server, just 3.5MB in size.
|
||||
- A tiny web server, just 5 MB in size.
|
||||
- Statically compiled binary with no dependencies.
|
||||
- Built for Docker.
|
||||
- Supports HTTPS.
|
||||
- Supports custom 404 file.
|
||||
- Supports custom index files for URLs ending with "/".
|
||||
- Takes care to not serve hidden files.
|
||||
- Adds caching headers automatically.
|
||||
- Does not support HTTPS. It is expected that you run it behind a reverse-proxy server with HTTPS support, like nginx.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -30,10 +29,14 @@ CMD ["/usr/bin/hastatic"]
|
||||
|
||||
Build and run:
|
||||
|
||||
```
|
||||
```bash
|
||||
$ docker build -t mywebsite .
|
||||
$ docker run -p 8080:3000 mywebsite # run with default configs
|
||||
$ # run with default configs
|
||||
$ docker run -p 8080:3000 mywebsite
|
||||
$ # run with custom configs
|
||||
$ docker run -e PORT=2000 -e NF_FILE=404.html -e IDX_FILE=index.html -p 8080:2000 mywebsite
|
||||
$ # run with HTTPS support
|
||||
$ docker run -e TLS_CERT_FILE=certificate.pem -e TLS_KEY_FILE=key.pem -p 443:3000 mywebsite
|
||||
```
|
||||
|
||||
## Configuration
|
||||
@ -43,7 +46,9 @@ The Docker image supports these environment variable for configuration:
|
||||
- PORT: the port to run the web server on, default: 3000
|
||||
- NF_FILE: name of the custom 404 file, default: `404.html`
|
||||
- IDX_FILE: name of the custom index files, default: `index.html`
|
||||
- TLS_CERT_FILE: TLS certification file, optional, required for HTTPS support
|
||||
- TLS_KEY_FILE: TLS key file, optional, required for HTTPS support
|
||||
|
||||
## Internals
|
||||
|
||||
_hastatic_ is written in Haskell, just 30 lines of it. It uses the excellent [Warp](https://hackage.haskell.org/package/warp) server underneath.
|
||||
_hastatic_ is written in Haskell, just 60 lines of it. It uses the excellent [Warp](https://hackage.haskell.org/package/warp) server underneath with the [warp-tls](https://hackage.haskell.org/package/warp-tls) package for TLS support.
|
||||
|
@ -2,7 +2,7 @@
|
||||
--
|
||||
-- see: https://github.com/sol/hpack
|
||||
--
|
||||
-- hash: e49204f2f26a2ed8552e95f4f543b1cb4148cc509790f5d550ab98b70a722323
|
||||
-- hash: e7a5e0192bba9ed055c360b88189436d278d96883c36e66a4a17b70f134f4654
|
||||
|
||||
name: hastatic
|
||||
version: 0.9.0
|
||||
@ -31,4 +31,5 @@ executable hastatic
|
||||
, wai
|
||||
, wai-middleware-static
|
||||
, warp
|
||||
, warp-tls
|
||||
default-language: Haskell2010
|
||||
|
@ -25,6 +25,7 @@ executables:
|
||||
dependencies:
|
||||
- wai
|
||||
- warp
|
||||
- warp-tls
|
||||
- http-types
|
||||
- wai-middleware-static
|
||||
- text
|
||||
|
58
src/Main.hs
58
src/Main.hs
@ -5,12 +5,16 @@ import Data.Maybe (fromMaybe)
|
||||
import qualified Data.List as List
|
||||
import qualified Data.Text as T
|
||||
import Network.Wai
|
||||
import qualified Network.Wai.Handler.WarpTLS as TLS
|
||||
import Network.Wai.Middleware.Static
|
||||
import Network.HTTP.Types (status404)
|
||||
import Network.Wai.Handler.Warp (run)
|
||||
import Network.Wai.Handler.Warp (run, defaultSettings, setPort)
|
||||
import System.Exit (die)
|
||||
import System.Environment (lookupEnv)
|
||||
import Text.Read (readMaybe)
|
||||
|
||||
data TLS = Okay TLS.TLSSettings | Error String | None
|
||||
|
||||
indexHTML :: T.Text -> Middleware
|
||||
indexHTML indexFile app req respond =
|
||||
let path = pathInfo req
|
||||
@ -22,22 +26,48 @@ indexHTML indexFile app req respond =
|
||||
[x] -> if "." `T.isInfixOf` x then [x] else [x, indexFile]
|
||||
(x:xs) -> x : fixPath xs
|
||||
|
||||
notFoundHandler :: FilePath -> Application
|
||||
notFoundHandler notFoundFile _ respond = respond $
|
||||
responseFile status404 [("Content-Type", "text/html")] notFoundFile Nothing
|
||||
|
||||
main = do
|
||||
mPort <- lookupEnv "PORT"
|
||||
let port = fromMaybe 3000 (readMaybe =<< mPort)
|
||||
mNotFoundFile <- lookupEnv "NF_FILE"
|
||||
let notFoundFile = fromMaybe "404.html" mNotFoundFile
|
||||
mIndexFile <- lookupEnv "IDX_FILE"
|
||||
let indexFile = T.pack $ fromMaybe "index.html" mIndexFile
|
||||
getTLSSettings :: IO TLS
|
||||
getTLSSettings = do
|
||||
tlsCertFile <- lookupEnv "TLS_CERT_FILE"
|
||||
tlsKeyFile <- lookupEnv "TLS_KEY_FILE"
|
||||
|
||||
cache <- initCaching PublicStaticCaching
|
||||
putStrLn $ "Starting server on port: " <> show port
|
||||
run port
|
||||
$ indexHTML indexFile
|
||||
$ staticPolicy' cache (predicate noDot)
|
||||
$ notFoundHandler notFoundFile
|
||||
case (tlsCertFile, tlsKeyFile) of
|
||||
(Nothing, Nothing) -> return None
|
||||
(Just cert, Just key) -> return $ Okay $ TLS.tlsSettings cert key
|
||||
_ -> return $ Error "Certificate file or Key file is missing"
|
||||
|
||||
application :: [FilePath] -> IO Application
|
||||
application excludedPaths = do
|
||||
notFoundFile <- fromMaybe "404.html" <$> lookupEnv "NF_FILE"
|
||||
indexFile <- T.pack . fromMaybe "index.html" <$> lookupEnv "IDX_FILE"
|
||||
cache <- initCaching PublicStaticCaching
|
||||
return
|
||||
. indexHTML indexFile
|
||||
. staticPolicy' cache polcy
|
||||
. notFoundHandler
|
||||
$ notFoundFile
|
||||
where
|
||||
noDot = not . List.isPrefixOf "."
|
||||
polcy = predicate noDot >-> predicate (not . flip elem excludedPaths)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
mPort <- lookupEnv "PORT"
|
||||
let port = fromMaybe 3000 (readMaybe =<< mPort)
|
||||
tlsSettings <- getTLSSettings
|
||||
|
||||
case tlsSettings of
|
||||
Okay tls -> do
|
||||
app <- application [TLS.certFile tls, TLS.keyFile tls]
|
||||
putStrLn $ "Starting HTTPS server on port: " <> show port
|
||||
TLS.runTLS tls (setPort port defaultSettings) app
|
||||
None -> do
|
||||
app <- application []
|
||||
putStrLn $ "Starting HTTP server on port: " <> show port
|
||||
run port app
|
||||
Error msg ->
|
||||
die $ "Error starting server: " <> msg
|
||||
|
Loading…
Reference in New Issue
Block a user