Search code examples
haskellscotty

Most elegant way to start several scotty servers in the same application?


Is there a standard way to start two scotty servers in the same application? In a toy project I'm trying:

main :: IO ()
main = do
  scotty 3000 $ do
    get "/" $ do
      text "hello"
  scotty 4000 $ do
    post "/" $ do
      text "world"

The first server spins up but the second one does not. It could also be a flaw in the way I'm understanding Haskell IO. Thanks!


Solution

  • The scotty procedure does not return, it takes over control and continually serves requests to the webroutes. If it did return then you'd have an issue with control flow - how would you keep the port open for when a request arrived?

    One solution is to put each call to scotty in a separate thread. For example:

    #!/usr/bin/env cabal
    {- cabal:
         build-depends: base, scotty
    -}
    {-# LANGUAGE OverloadedStrings #-}
    
    import Control.Concurrent
    import Web.Scotty
    
    main :: IO ()
    main = do
      forkIO $ scotty 3000 $ do
        get "/" $ do
          text "hello"
      scotty 4000 $ do
        post "/" $ do
          text "world"
    

    With operation of:

    % curl -XPOST localhost:4000
    world%
    % curl -XGET localhost:3000
    hello%