wai-enforce-https: Enforce HTTPS in Wai server app safely.

[ bsd3, library, web ] [ Propose Tags ]

Wai middleware enforcing HTTPS protocol on any incoming request. In case of non-encrypted HTTP, traffic is redirected using 301 Permanent Redirect or optionally 307 Temporary Redirect. Middleware has compatibility modes for various reverse proxies (load balancers) and therefore can be used with Heroku, Google Cloud (Ingress), Azure or any other type of PAS or Cloud provider.


[Skip to Readme]

Flags

Automatic Flags
NameDescriptionDefault
examples

Build example projects

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.0.1, 0.0.2, 0.0.2.1, 1.0.0.0
Change log CHANGELOG.md
Dependencies base (>=4 && <5), bytestring, case-insensitive, http-types, network, text, wai, wai-enforce-https, warp, warp-tls [details]
License BSD-3-Clause
Author Marek Fajkus
Maintainer marek.faj@gmail.com
Category Web
Home page https://github.com/turboMaCk/wai-enforce-https
Source repo head: git clone https://github.com/turboMaCk/wai-enforce-https.git
Uploaded by MarekFajkus at 2021-11-01T17:19:41Z
Distributions LTSHaskell:1.0.0.0, NixOS:1.0.0.0, Stackage:1.0.0.0
Executables example-proxy, example-tls
Downloads 1231 total (14 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2021-11-01 [all 1 reports]

Readme for wai-enforce-https-1.0.0.0

[back to package description]

Wai Enforce HTTPS

build

Safely enforce HTTPS in wai application

Wai middleware enforcing HTTPS protocol on any incoming request. In case of non-encrypted HTTP, traffic is redirected using 301 Permanent Redirect or optionally 307 Temporary Redirect.

Middleware has compatibility modes for various reverse proxies (load balancers) and therefore can be used with Heroku, Google Cloud (Ingress), Azure or any other type of PAS or Cloud provider.

Comparison with ForceSSL

Wai-Extra package comes with Network.Wai.Middleware.ForceSSL module exposing middleware intended for the same purpose. There are several practical weaknesses of this implementation compare to one provided by wai-enforce-https.

Behavior EnforceHTTPS (wai-enforce-https) ForceSSL (wai-extra)
Redirecting methods by default GET, HEAD (by default) All
Redirect status 301 (default) or 307 (optional) 307
Safe against header spoofing ✔ yes ❌ no
Forwarded spec compliant ✔ yes ❌ no
Configurable port ✔ yes ❌ no
Configurable host ✔ yes ❌ no
405 with Allow header support ✔ yes ❌ no

Overall, this package aims to be secure by default and configurable as much as possible to fit any specific needs.

Forwarded

In addition to the main functionality (enforcement of HTTPS) this package also comes with module for parsing and encoding Forwarded HTTP header.

Examples

This example is using warp-tls and runs 2 servers:

  • HTTP server on port 8080
  • HTTPS server on port 8443

if you open http://127.0.0.1:8080 in browser server returns redirect to https://127.0.0.1:8443

{-# LANGUAGE OverloadedStrings #-}

module Main where

import           Control.Concurrent                  (forkIO)
import           Network.HTTP.Types                  (status200)
import           Network.Wai                         (Application, responseLBS)
import           Network.Wai.Handler.Warp            (defaultSettings, run,
                                                      setPort)
import           Network.Wai.Handler.WarpTLS         (runTLS, tlsSettings)
import           Network.Wai.Middleware.EnforceHTTPS (EnforceHTTPSConfig (..))

import qualified Network.Wai.Middleware.EnforceHTTPS as EnforceHTTPS

handler :: Application
handler _ respond =
   respond $ responseLBS status200 [] "Hello over HTTPS"

httpsConf :: EnforceHTTPSConfig
httpsConf = EnforceHTTPS.defaultConfig { httpsPort = 8443 }

app :: Application
app = EnforceHTTPS.withConfig httpsConf handler

main :: IO ()
main = do
  let tls = tlsSettings "examples/cert.pem" "examples/key.pem"
  _ <- forkIO $ run 8080 app
  runTLS tls (setPort (httpsPort httpsConf) defaultSettings) app

Another common example is running server behind reverse proxy. Say for instance we want to host our app on Heroku while using its https support and make sure we redirect all HTTP traffic to HTTPS. Heroku is forwarding traffic with additional header containing information about protocol named x-forwarded-proto.

{-# LANGUAGE OverloadedStrings #-}

module Main where

import           Network.HTTP.Types                  (status200)
import           Network.Wai                         (Application, responseLBS)
import           Network.Wai.Handler.Warp            (runEnv)

import qualified Network.Wai.Middleware.EnforceHTTPS as EnforceHTTPS

handler :: Application
handler _ respond = respond $
  responseLBS status200 [] "Hello from behind proxy"

app :: Application
app = EnforceHTTPS.withResolver EnforceHTTPS.xForwardedProto handler

main :: IO ()
main = runEnv 8080 app

Bulding Examples

In order to run examples project must be build with examples flag:

$ cabal build -f examples

Credits

Design of this library is heavily based on my other project koa-sslify and is based on feedback and work of contributors of this library.