Warp Port Reuse

Hello, I wonder how to pass “Reuse Port” option into the Warp settings so that on server restart, those “Address in use” error never appears. I use “CTRL+C” to close the current running Warp server, and use stack run to run it.

import Network.Wai.Handler.Warp (setPort, defaultSettings)
warpOpts = setPort 8080 defaultSettings

Error:

Network.Socket.bind: resource busy (Address already in use)

Might be possible to reuse the port, but i would have tried to make ctrl-c do a clean shutdown.

1 Like

Here’s how you can set SO_REUSEADDR to allow re-using the port immediately.

  • Get a port yourself using bindPortTCP.
  • Use setSocketOption socket ReuseAddr 1 to allow immediate reuse.
  • Use your own port via Warp.runSettingsSocket.
#!/usr/bin/env stack
-- stack script --compile --resolver lts-20.18 --package warp --package wai --package http-types --package streaming-commons --package network

{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS -Wall #-}

module Main where

import           Control.Exception (bracket)
import           Data.Streaming.Network (bindPortTCP)
import           Network.Wai (responseLBS)
import qualified Network.Socket as Socket
import           Network.HTTP.Types.Status (status200)
import qualified Network.Wai.Handler.Warp as Warp

main :: IO ()
main = do
  bracket (bindPortTCP 1234 "*") Socket.close' $ \socket -> do

    putStrLn "Got socket, setting SO_REUSEADDR"
    Socket.setSocketOption socket Socket.ReuseAddr 1

    Warp.runSettingsSocket Warp.defaultSettings socket $ \_req respond -> do
      putStrLn "responding to request"
      respond $ responseLBS status200 [] "hi"

Run with e.g. stack Main.hs.

Test with curl 'http://localhost:1234'.

2 Likes