aboutsummaryrefslogtreecommitdiff
path: root/src/Main.hs
blob: 5ab2322f15621014038be8441391f1a0e9d044e4 (plain)
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
{-# LANGUAGE OverloadedStrings, QuasiQuotes, TemplateHaskell,
    TypeFamilies, ViewPatterns, LambdaCase #-}

module Main (main) where

import Yesod
import Network.Wai.Handler.Warp
import Data.Function ((&))
import Data.Functor ((<&>))

import qualified Data.ByteString as BS

import Bangs
import BangState
import Config

data Search = Search {
    bangState :: BangState
}

mkYesod "Search" [parseRoutes|
/           HomeR GET
/bundle.js  BundleR GET
/bangs.json BangsR GET
/submitBang SubmitR POST
/search.xml OpenSearchR GET
|]

instance Yesod Search where
    makeSessionBackend _ = return Nothing

getHomeR :: Handler ()
getHomeR = sendFile typeHtml "frontend/index.html"

getBundleR :: Handler ()
getBundleR = sendFile typeJavascript "frontend/bundle.js"

getBangsR :: Handler TypedContent
getBangsR = do
    bangsAccessor <- lookupHeader "accept-encoding" >>= \case
        Just ae | "br" `BS.isInfixOf` ae -> do
            addHeader "content-encoding" "br"
            return getBangsBrotli
        _ -> do
            return getBangsJSON

    bs <- liftIO . bangsAccessor . bangState =<< getYesod
    return $ TypedContent typeJson $ toContent bs

postSubmitR :: Handler String
postSubmitR = return "TODO"

getOpenSearchR :: Handler TypedContent
getOpenSearchR = do
    url <- lookupGetParam "default" <&> \case
        Nothing -> baseUrl <> "/#{searchTerms}"
        Just b  -> baseUrl <> "/#" <> b <> "#{searchTerms}"

    return
        $ TypedContent "application/opensearchdescription+xml"
        $ toContent
        $ makeOpenSearch url

main :: IO ()
main = do
    s <- Search
        <$> initBangState

    sApp <- toWaiApp s -- includes middlewares
    let settings = defaultSettings
            -- currently, "*" seems to bind only to ipv4 while "*6" binds to both
            & setHost "*6"
            & setPort 20546
    runSettings settings sApp