Intial commit
commit
28a534d74d
|
@ -0,0 +1,3 @@
|
||||||
|
.stack-work/
|
||||||
|
abhinavsarkar-net-server.cabal
|
||||||
|
*~
|
|
@ -0,0 +1,7 @@
|
||||||
|
FROM haskell:8.4.3 as builder
|
||||||
|
WORKDIR /opt/hastatic
|
||||||
|
ADD . .
|
||||||
|
RUN stack install && strip /root/.local/bin/hastatic
|
||||||
|
|
||||||
|
FROM fpco/haskell-scratch:integer-gmp
|
||||||
|
COPY --from=builder /root/.local/bin/hastatic /usr/bin/hastatic
|
|
@ -0,0 +1,30 @@
|
||||||
|
Copyright Abhinav Sarkar (c) 2018
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Abhinav Sarkar nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,45 @@
|
||||||
|
# hastatic
|
||||||
|
|
||||||
|
_hastatic_ is a tiny static web server for Docker.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- A tiny web server, just 3MB in size.
|
||||||
|
- Statically compiled binary with no dependencies.
|
||||||
|
- Built for Docker.
|
||||||
|
- Supports custom 404 file.
|
||||||
|
- Supports custom index files for URLs ending with "/".
|
||||||
|
- 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
|
||||||
|
|
||||||
|
Create a Dockerfile for your website, deriving from `abhin4v/hastatic`:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM abhin4v/hastatic:latest
|
||||||
|
|
||||||
|
COPY mywebsite /opt/mywebsite
|
||||||
|
WORKDIR /opt/mywebsite
|
||||||
|
CMD ["/usr/bin/hastatic"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Build and run:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker build -t mywebsite .
|
||||||
|
$ docker run -p 8080:3000 mywebsite # run with default configs
|
||||||
|
$ docker run -e PORT=2000 -e NF_FILE=404.html -e IDX_FILE=index.html -p 8080:2000 mywebsite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
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`
|
||||||
|
|
||||||
|
## Internals
|
||||||
|
|
||||||
|
_hastatic_ is written in Haskell, just 30 lines of it. It uses the excellent [Warp](https://hackage.haskell.org/package/warp) server underneath.
|
|
@ -0,0 +1,34 @@
|
||||||
|
-- This file has been generated from package.yaml by hpack version 0.28.2.
|
||||||
|
--
|
||||||
|
-- see: https://github.com/sol/hpack
|
||||||
|
--
|
||||||
|
-- hash: e49204f2f26a2ed8552e95f4f543b1cb4148cc509790f5d550ab98b70a722323
|
||||||
|
|
||||||
|
name: hastatic
|
||||||
|
version: 0.9.0
|
||||||
|
description: Please see the README on GitHub at <https://github.com/abhin4v/hastatic#readme>
|
||||||
|
author: Abhinav Sarkar
|
||||||
|
maintainer: abhinav@abhinavsarkar.net
|
||||||
|
copyright: 2018 Abhinav Sarkar
|
||||||
|
license: BSD3
|
||||||
|
license-file: LICENSE
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >= 1.10
|
||||||
|
extra-source-files:
|
||||||
|
README.md
|
||||||
|
|
||||||
|
executable hastatic
|
||||||
|
main-is: Main.hs
|
||||||
|
other-modules:
|
||||||
|
Paths_hastatic
|
||||||
|
hs-source-dirs:
|
||||||
|
src
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N -O2
|
||||||
|
build-depends:
|
||||||
|
base >=4.7 && <5
|
||||||
|
, http-types
|
||||||
|
, text
|
||||||
|
, wai
|
||||||
|
, wai-middleware-static
|
||||||
|
, warp
|
||||||
|
default-language: Haskell2010
|
|
@ -0,0 +1,30 @@
|
||||||
|
name: hastatic
|
||||||
|
version: 0.9.0
|
||||||
|
license: BSD3
|
||||||
|
author: "Abhinav Sarkar"
|
||||||
|
maintainer: "abhinav@abhinavsarkar.net"
|
||||||
|
copyright: "2018 Abhinav Sarkar"
|
||||||
|
|
||||||
|
extra-source-files:
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
description: Please see the README on GitHub at <https://github.com/abhin4v/hastatic#readme>
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base >= 4.7 && < 5
|
||||||
|
|
||||||
|
executables:
|
||||||
|
hastatic:
|
||||||
|
main: Main.hs
|
||||||
|
source-dirs: src
|
||||||
|
ghc-options:
|
||||||
|
- -threaded
|
||||||
|
- -rtsopts
|
||||||
|
- -with-rtsopts=-N
|
||||||
|
- -O2
|
||||||
|
dependencies:
|
||||||
|
- wai
|
||||||
|
- warp
|
||||||
|
- http-types
|
||||||
|
- wai-middleware-static
|
||||||
|
- text
|
|
@ -0,0 +1,43 @@
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
import qualified Data.List as List
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Network.Wai
|
||||||
|
import Network.Wai.Middleware.Static
|
||||||
|
import Network.HTTP.Types (status404)
|
||||||
|
import Network.Wai.Handler.Warp (run)
|
||||||
|
import System.Environment (lookupEnv)
|
||||||
|
import Text.Read (readMaybe)
|
||||||
|
|
||||||
|
indexHTML :: T.Text -> Middleware
|
||||||
|
indexHTML indexFile app req respond =
|
||||||
|
let path = pathInfo req
|
||||||
|
in flip app respond $ req { pathInfo = fixPath path }
|
||||||
|
where
|
||||||
|
fixPath path = case path of
|
||||||
|
[] -> [indexFile]
|
||||||
|
[""] -> [indexFile]
|
||||||
|
[x] -> if "." `T.isInfixOf` x then [x] else [x, indexFile]
|
||||||
|
(x:xs) -> x : fixPath xs
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
cache <- initCaching PublicStaticCaching
|
||||||
|
putStrLn $ "Starting server on port: " <> show port
|
||||||
|
run port
|
||||||
|
$ indexHTML indexFile
|
||||||
|
$ staticPolicy' cache (predicate noDot)
|
||||||
|
$ notFoundHandler notFoundFile
|
||||||
|
where
|
||||||
|
noDot = not . List.isPrefixOf "."
|
|
@ -0,0 +1,4 @@
|
||||||
|
resolver: lts-12.1
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- .
|
Loading…
Reference in New Issue