Web Application in Haskell
This publication will introduce you into development process of web application with usage of Haskell programming language. I would like you to have a clue about “How does the internet work?” and “What is HTTP?” before we will proceed into intial chapter.
Iterative server loop
In casual web (application) development you would rather choose a library with would abstract this mechanism away, althrough it’s not very complicated when we strip away in-depth knowledge about how servers work with TCP sockets.
create socket
bind(address, port)
listen()
while true:
conn, client_addr = accept()
handle(conn) # then close
That is the classic iterative server loop. Everything else (threads, async, frameworks) is just a way to handle the connections more efficiently.
Implementation
We use Network.Socket, Network.HTTP, and Network.URI libraries which are considered low-level packages and are necessary to implement iterative server loop directly.
module Main (main) where
import Control.Monad (forever)
import Network.HTTP
( Request(rqURI)
, Response(..)
, close
, receiveHTTP
, respondHTTP
, socketConnection
)
import Network.Socket
( Family(AF_INET)
, SocketType(Stream)
, SockAddr(SockAddrInet)
, accept
, bind
, defaultProtocol
, listen
, socket
, tupleToHostAddress
)
import Network.URI (uriPath)
main :: IO ()
main = do
lsock <- socket AF_INET Stream defaultProtocol
bind lsock (SockAddrInet 8080 (tupleToHostAddress (0, 0, 0, 0)))
listen lsock 1
forever $ do
(csock, _) <- accept lsock
hs <- socketConnection "" 8080 csock
req <- receiveHTTP hs
case req of
Left _ -> close hs
Right r -> do
let path = uriPath (rqURI r)
resp
| path == "/" = Response (2,0,0) "OK" [] "Hello, World!\n"
| otherwise = Response (4,0,4) "Not Found" [] "Nothing here\n"
respondHTTP hs resp
close hs
It’s a simple web application you could ever seen which greets a user when access through HTTP with "Hello World".
Running the application
To run this application, you will need a local Haskell development environment with Cabal installed.
Cabal file
Create a haskell.cabal file in your project root with the following configuration:
cabal-version: 3.0
name: haskell
version: 0.1.0.0
license: BSD-3-Clause
license-file: LICENSE
author: keinsell
maintainer: [email protected]
build-type: Simple
extra-doc-files: CHANGELOG.md
common warnings
ghc-options: -Wall
executable haskell
import: warnings
main-is: Main.hs
build-depends:
base ^>=4.21.0.0,
network ^>=3.2.8.0,
HTTP ^>=4000.4.1,
network-uri ^>=2.6.4.2
hs-source-dirs: app
default-language: Haskell2010
Key takeaway: The main entry point is expected at
app/Main.hs, and the four low-level libraries (base,network,HTTP, andnetwork-uri) must be specified underbuild-depends.
Manually test your application
Initialize and launch the server application directly through Cabal:
cabal run
Once the server is running, open a separate terminal window to test the endpoints:
curl http://localhost:8080/
# Output: Hello, World!
curl http://localhost:8080/foo
# Output: Nothing here
There’s a long way ahead.
There’s a lot of what we didn’t touched and what have been showed up there is a drop of a water in the sea of what is left unsaid there.
The next phase involves implementing routing and configuring HTML page rendering, until introduction of usage of major libraries.
Back to Blog