Skip to content

Commit

Permalink
Simplify request creation logic
Browse files Browse the repository at this point in the history
Previously, we were using `SimpleQuery` inside our Endpoint type, but
ultimately that meant pushing the work of creating those into the
endpoint creation. Ultimately, I think that's probably too noisy, and
that we can get by with a simple `(Text, Text)` representation of these
queries.

This leaves us in a bind though, because our upload endpoint is going to
deal with ByteString already. Moving that back and forth from Text to
ByteString seems like a waste of time, so I'd like to try to avoid that.

We can solve this issue by conflating the request method and the body
data into a sum type. We can then use this sum type to not only
differentiate between the different body formats, but also to determine
how to encode the particular body types for the request.
  • Loading branch information
gfontenot committed Apr 4, 2017
1 parent ecbde9b commit 9dadbaf
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 23 deletions.
19 changes: 11 additions & 8 deletions src/Helper/Twitter/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Helper.Twitter.Types

makeRequest :: Endpoint -> Handler Request
makeRequest e = parseRequest (url (endpointDomain e) (endpointPath e))
>>= addParams e
>>= addBody (endpointBody e)
>>= forceSecure
>>= signed

Expand All @@ -28,12 +28,15 @@ signed req = do
forceSecure :: Request -> Handler Request
forceSecure = return . setRequestSecure True

addParams :: Endpoint -> Request -> Handler Request
addParams (Endpoint _ _ POSTRequest b) = return . urlEncodedBody b
addParams (Endpoint _ _ MultipartRequest b) = formDataBody (formBody b)
addBody :: Body -> Request -> Handler Request
addBody (PostBody b) = return . encodedBody b
addBody (MultipartBody b) = formDataBody (formBody b)

formBody :: SimpleQuery -> [Part]
formBody b = map queryToPart b
encodedBody :: [(Text, Text)] -> Request -> Request
encodedBody = urlEncodedBody . map toQueryItem
where
queryToPart :: SimpleQueryItem -> Part
queryToPart (k, v) = partBS (decodeUtf8 k) v
toQueryItem :: (Text, Text) -> SimpleQueryItem
toQueryItem (k, v) = (encodeUtf8 k, encodeUtf8 v)

formBody :: [(Text, ByteString)] -> [Part]
formBody = map (uncurry partBS)
14 changes: 5 additions & 9 deletions src/Helper/Twitter/Endpoints.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,19 @@ module Helper.Twitter.Endpoints
import Import
import Helper.Twitter.Types

import qualified Data.ByteString.Char8 as BS

updateStatusEndpoint :: Text -> [Text] -> Endpoint
updateStatusEndpoint status images = Endpoint
{ endpointDomain = "api"
, endpointPath = "statuses/update.json"
, endpointType = POSTRequest
, endpointBody = [
(BS.pack "status", encodeUtf8 status),
(BS.pack "media_ids", encodeUtf8 $ intercalate "," images)
]
, endpointBody = PostBody
[ ("status", status)
, ("media_ids", intercalate "," images)
]
}

uploadMediaEndpoint :: ByteString -> Endpoint
uploadMediaEndpoint fileData = Endpoint
{ endpointDomain = "upload"
, endpointPath = "media/upload.json"
, endpointType = MultipartRequest
, endpointBody = [(BS.pack "media", fileData)]
, endpointBody = MultipartBody [("media", fileData)]
}
9 changes: 3 additions & 6 deletions src/Helper/Twitter/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Helper.Twitter.Types
, Credentials(..)
, Tweet(..)
, Media(..)
, RequestType(..)
, Body(..)
) where

import ClassyPrelude.Yesod
Expand Down Expand Up @@ -32,14 +32,12 @@ instance FromJSON Media where

return Media {..}

data RequestType = POSTRequest | MultipartRequest
deriving (Eq, Show)
data Body = PostBody [(Text, Text)] | MultipartBody [(Text, ByteString)]

data Endpoint = Endpoint
{ endpointDomain :: String
, endpointPath :: String
, endpointType :: RequestType
, endpointBody :: SimpleQuery
, endpointBody :: Body
}

data Credentials = Credentials
Expand All @@ -57,4 +55,3 @@ instance FromJSON Credentials where
twitterAccessTokenSecret <- o .: "access-token-secret"

return Credentials {..}

0 comments on commit 9dadbaf

Please sign in to comment.