-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMain.hs
81 lines (67 loc) · 2.44 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative ((<$>))
import Data.Binary (encode)
import qualified Data.ByteString.Char8 as Char
import Data.Global (declareIORef)
import Data.IORef (IORef, readIORef, modifyIORef)
import Data.Maybe (fromJust)
import Data.Text as Text
import Network.HTTP.Types (status201, status302, status404)
import Network.Wai (Request, Response, pathInfo, responseLBS, queryString, ResponseReceived)
import Network.Wai.Handler.Warp (run)
import System.Environment (getEnvironment)
import Shortener
world :: IORef World
world = declareIORef "world" initialWorld
main :: IO ()
main = do
env <- getEnvironment
let port = maybe 8080 read $ lookup "PORT" env
run port app
app :: Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
app request respond = do
response <- dispatch request
respond response
dispatch :: Request -> IO Response
dispatch request = case pathInfo request of
[] -> return indexHandler
["shorten"] -> shortenHandler request
_ -> expandHandler request
indexHandler :: Response
indexHandler = redirectTo "https://github.com/justincampbell/url-shorteners"
redirectTo :: Char.ByteString -> Response
redirectTo url = responseLBS status302 [("Location", url)] ""
shortenHandler :: Request -> IO Response
shortenHandler request = do
let
url = extractUrl request
headers = []
_ <- updateShortenIORef url
token <- lastToken <$>
readIORef world
let
body = encode $ "/" ++ token
return $ responseLBS status201 headers body
extractUrl :: Request -> Url
extractUrl request = case url of
Just url' -> Char.unpack $ fromJust url'
Nothing -> ""
where url = lookup "url" $ queryString request
expandHandler :: Request -> IO Response
expandHandler request = do
url <- expandTokenIORef $ extractToken request
case url of
Nothing -> return $ responseLBS status404 [] ""
Just url' -> return $ redirectTo $ Char.pack url'
extractToken :: Request -> Token
extractToken request =
case pathInfo request of
[] -> Text.unpack ""
[a] -> Text.unpack a
_ -> ""
updateShortenIORef :: Url -> IO ()
updateShortenIORef url = modifyIORef world (shorten url)
expandTokenIORef :: Token -> IO (Maybe Url)
expandTokenIORef token = do
currentWorld <- readIORef world
return $ expand token currentWorld