Http decodes data with aeson

This commit is contained in:
towards-a-new-leftypol 2024-01-13 12:52:03 -05:00
parent 3b59fe8534
commit 27a156f4e5
6 changed files with 37 additions and 44 deletions

View File

@ -67,6 +67,7 @@ executable chandlr
Network.Http Network.Http
Network.Client Network.Client
Routes Routes
Common.PostsType
-- LANGUAGE extensions used by modules in this package. -- LANGUAGE extensions used by modules in this package.
-- other-extensions: -- other-extensions:
@ -79,7 +80,8 @@ executable chandlr
servant, servant,
ghcjs-dom, ghcjs-dom,
ghcjs-dom-jsffi, ghcjs-dom-jsffi,
text text,
time
-- Directories containing source files. -- Directories containing source files.
hs-source-dirs: src hs-source-dirs: src

View File

@ -4,6 +4,8 @@ import Component.CatalogGrid as Grid
import Network.Client as Client import Network.Client as Client
import Data.Text (Text) import Data.Text (Text)
import Common.PostsType (Post)
data Action data Action
= GridAction Grid.Action = GridAction Grid.Action
| GetLatest | GetLatest
@ -12,6 +14,6 @@ data Action
, board :: String , board :: String
, board_thread_id :: Int , board_thread_id :: Int
} }
| HaveLatest (Client.HttpResult Text) | HaveLatest (Client.HttpResult [Post])
| ClientAction Client.Action | ClientAction Client.Action
| NoAction | NoAction

@ -1 +1 @@
Subproject commit 0026e48cea06e2768f7a22f4a25bf115debcea35 Subproject commit a5d90ea96195ed6a5a7e3196d5b0e32b65af5058

View File

@ -100,8 +100,8 @@ mainUpdate (HaveLatest (Client.HttpResponse {..})) m = m <# do
case body of case body of
Nothing -> do Nothing -> do
consoleLog "Didn't get anything back from API" consoleLog "Didn't get anything back from API"
Just txt -> do Just posts -> do
consoleLog $ toJSString txt consoleLog $ toJSString $ show posts
return NoAction return NoAction

View File

@ -20,14 +20,15 @@ import Control.Concurrent.MVar (takeMVar)
import Miso (effectSub, Effect) import Miso (effectSub, Effect)
import qualified Network.Http as Http import qualified Network.Http as Http
import Common.PostsType (Post)
data Action = Connect Http.HttpActionResult data Action = Connect (Http.HttpActionResult [Post])
data Interface a = Interface data Interface a = Interface
{ passAction :: Action -> a { passAction :: Action -> a
, returnResult :: Http.HttpResult Text -> a , returnResult :: Http.HttpResult [Post] -> a
} }
@ -44,7 +45,7 @@ update
-> Effect a Model -> Effect a Model
update iface (Connect (abort, resultVar)) m = effectSub m $ update iface (Connect (abort, resultVar)) m = effectSub m $
\sink -> void $ forkIO $ do \sink -> void $ forkIO $ do
result :: Http.HttpResult Text <- takeMVar resultVar result :: Http.HttpResult [Post] <- takeMVar resultVar
sink $ (returnResult iface) result sink $ (returnResult iface) result

View File

@ -10,8 +10,10 @@ where
import Prelude hiding (error) import Prelude hiding (error)
import Data.Text (Text) import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8)
import Control.Monad.IO.Class (liftIO) import Control.Monad.IO.Class (liftIO)
import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar) import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar)
import Data.Aeson (FromJSON, eitherDecodeStrict)
import GHCJS.DOM.XMLHttpRequest import GHCJS.DOM.XMLHttpRequest
( newXMLHttpRequest ( newXMLHttpRequest
, openSimple , openSimple
@ -27,33 +29,6 @@ import Data.JSString.Text (textToJSString)
import GHCJS.DOM.EventM (onAsync) import GHCJS.DOM.EventM (onAsync)
import GHCJS.DOM.XMLHttpRequestEventTarget (load, abortEvent, error) import GHCJS.DOM.XMLHttpRequestEventTarget (load, abortEvent, error)
-- What we actually want is to call send and not block the thread
-- - so that we can put the request into our list of ongoing requests.
-- - and have the response come back as an Action?
-- - we would need the onload event to send an Action to updateModel
{-
- Okay what the hell do I even want from an http function?
-
- the js implementation has these features:
-
- - url
- - method
- - ability to abort
- - is async
- - get the result from it
- - this should be a fn (IO result), let's not expose the xhr object?
-
- Also want:
- - return the same data structure always, but that data structure should
- inform of any errors, and have the status code, response body,
- and status text.
-
-
- Do we really need some sort of isomorphic framework? I think that's
- more work than just using a simple http lib server-side... tbqh
-}
data HttpMethod = GET | PUT | POST | DELETE | PATCH data HttpMethod = GET | PUT | POST | DELETE | PATCH
deriving Show deriving Show
@ -65,10 +40,10 @@ data HttpResult a
, body :: Maybe a , body :: Maybe a
} }
type HttpActionResult = (IO (), MVar (HttpResult Text)) -- (abort, result) type HttpActionResult a = (IO (), MVar (HttpResult a)) -- (abort, result)
mkResult :: XMLHttpRequest -> IO (HttpResult Text) mkResult :: (FromJSON a) => XMLHttpRequest -> IO (HttpResult a)
mkResult xhr = do mkResult xhr = do
sc <- getStatus xhr sc <- getStatus xhr
@ -78,18 +53,31 @@ mkResult xhr = do
mBody :: Maybe Text <- getResponseText xhr mBody :: Maybe Text <- getResponseText xhr
return HttpResponse let mBytes = mBody >>= Just . encodeUtf8
{ status_code = status_code_int
, status_text = st case mBytes of
, body = mBody Nothing -> return HttpResponse
} { status_code = status_code_int
, status_text = st
, body = Nothing
}
Just bs -> do
let parse_result = eitherDecodeStrict bs
case parse_result of
Left _ -> return Error
Right x -> return HttpResponse
{ status_code = status_code_int
, status_text = st
, body = Just x
}
http http
:: String :: (FromJSON a)
=> String
-> HttpMethod -> HttpMethod
-> Maybe Text -> Maybe Text
-> IO HttpActionResult -> IO (HttpActionResult a)
http url method payload = do http url method payload = do
xhr <- newXMLHttpRequest xhr <- newXMLHttpRequest