Advertisement
aircampro

haskell scotty webserver

Dec 7th, 2023 (edited)
4,985
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 4.01 KB | Software | 0 0
  1. -- Haskell webserver using scotty
  2. -- add users to the system and query them from the uid number
  3.  
  4. -- add to package yaml
  5. -- http-types
  6. -- aeson
  7. -- scotty
  8.  
  9. {-# LANGUAGE OverloadedStrings #-}
  10. {-# LANGUAGE DeriveGeneric #-}
  11.  
  12. module UserAPI where
  13.  
  14. import Web.Scotty
  15. import Data.Aeson (FromJSON, ToJSON)
  16. import GHC.Generics
  17. import Data.IORef
  18. import Control.Monad.Reader
  19. import Network.HTTP.Types.Status
  20. import Data.List (find)
  21. import System.Environment (lookupEnv)
  22. import System.IO
  23. import qualified Data.Text as T
  24. import qualified Data.Text.Encoding as T
  25. import qualified Codec.Text.IConv as I
  26. import qualified Data.ByteString.Lazy as L
  27.  
  28. -- the users of this server have a id, a name and a width, length & height, this can be used by the gripper
  29. data User = User { uid :: Integer, name :: String, width :: Double, height :: Double, len :: Double} deriving (Generic, Show)
  30. instance ToJSON User
  31. instance FromJSON User
  32.  
  33. -- this is a message which is relayed back after a characture substitute of . for !
  34. data Msg = Msg { uid :: Integer, message :: String} deriving (Generic, Show)
  35. instance ToJSON Msg
  36. instance FromJSON Msg
  37.  
  38. data Error = Error { message :: String } deriving (Generic, Show)
  39. instance ToJSON Error
  40. instance FromJSON Error
  41.  
  42. addUser :: [User] -> User -> [User]
  43. addUser users user = user:users
  44.  
  45. deleteUser :: [User] -> Integer -> [User]
  46. deleteUser users i = filter (\user -> uid user /= i) users
  47.  
  48. findUser :: [User] -> Integer -> Maybe User
  49. findUser users i = find (\u -> uid u == i) users
  50.  
  51. main :: IO ()
  52. main = do
  53.   users <- newIORef [] :: IO (IORef [User])
  54.   -- get the PORT from the port environment e.g. PORT=3000 ; export PORT
  55.   port <- maybe 3000 read <$> lookupEnv "PORT" :: IO Int
  56.   scotty (read port::Int) $ do
  57.     -- $ curl -X GET http://localhost:3000/users
  58.     get "/users" $ do
  59.       us <- liftIO (readIORef users)
  60.       status status200
  61.       json us
  62.     -- $ curl -X GET http://localhost:3000/users/1
  63.     get "/users/:uid" $ do
  64.       us <- liftIO (readIORef users)
  65.       i <- param "uid"
  66.       case findUser us (read i) of
  67.         Just u -> status status200 >> json u
  68.         Nothing -> status status404 >> json (Error ("Not Found uid = " <> i))
  69.     -- curl -X POST http://localhost:3000/users -d '{ "uid": 1, "name": "mid_size_box", "width": 34.67, "height": 12.9, "len": 1.12 }'
  70.     post "/users" $ do
  71.       u <- jsonData
  72.       us <- liftIO $ readIORef users
  73.       liftIO $ writeIORef users $ addUser us u
  74.       status status201
  75.       json u
  76.     -- curl -v -X DELETE http://localhost:3000/users/1
  77.     delete "/users/:uid" $ do
  78.       i <- param "uid"
  79.       us <- liftIO $ readIORef users
  80.       liftIO $ writeIORef users $ deleteUser us i
  81.       status status204
  82.     -- $ curl -X GET http://localhost:3000/html
  83.     get "/html" $ do
  84.       status status200
  85.       html "<h1>This is the scotty webserver! <br> writing some html........</h1>"
  86.     -- $ curl -X GET http://localhost:3000/text/charlie
  87.     get "/text/:you" $ do
  88.       you <- param "you"
  89.       us <- liftIO (readIORef users)
  90.       status status200
  91.       text ("Hello " <> you <> ", json is " <> (json us))
  92.     -- curl -X POST http://localhost:3000/msg -d '{ "uid": 1, "message": "this. is the message..." }' changes all . to ! before print
  93.     post "/msg" $ do
  94.       m <- jsonData
  95.       -- b <- message m or below is alternative
  96.       -- let (Msg a b) = m
  97.       -- let messge = T.pack b
  98.       (Msg a b) <- m
  99.       messge <- T.pack b
  100.       mm <- T.map (\c -> if c == '.' then '!' else c) messge
  101.       ll <- T.length messge
  102.       status status200
  103.       text ("length" <> ll <> " original message " <> b <> " changed " <> mm))
  104.     -- curl -X POST http://localhost:3000/fileshow
  105.     post "/fileshow" $ do
  106.       bs <- L.hGetContents =<< openBinaryFile "/home/mark/haskell/my_file.txt" ReadMode
  107.       status status200
  108.       text ($ T.replace "\r\n" "\n" (T.decodeUtf8 $ L.toStrict bs))
  109.     -- curl -D - http://localhost:8080/redirect/to/root
  110.     get "/redirect/to/root" $ do
  111.       status status302
  112.       setHeader "Haskell" "scotty"
  113.       redirect "/"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement