Skip to content

Commit

Permalink
feat: add multipart/form-data support
Browse files Browse the repository at this point in the history
  • Loading branch information
vst committed Sep 28, 2023
1 parent 2da21cb commit 1d67806
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
3 changes: 2 additions & 1 deletion decaf-client.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ homepage: https://github.com/teloscube/decaf-client-haskell#readme
bug-reports: https://github.com/teloscube/decaf-client-haskell/issues
author: Vehbi Sinan Tunalioglu
maintainer: [email protected]
copyright: 2020-2022 Teloscube Pte Ltd
copyright: 2020-2023 Teloscube Pte Ltd
license: BSD3
license-file: LICENSE
build-type: Simple
Expand Down Expand Up @@ -49,6 +49,7 @@ library
, bytestring
, case-insensitive
, exceptions
, http-client
, http-conduit
, http-types
, network-uri
Expand Down
1 change: 1 addition & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ library:
- bytestring
- case-insensitive
- exceptions
- http-client
- http-conduit
- http-types
- network-uri
Expand Down
20 changes: 20 additions & 0 deletions src/Decaf/Client/DecafRequest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Decaf.Client.DecafCredentials (DecafCredentials (DecafCredentialsHeader))
import Decaf.Client.DecafRemote (DecafRemote (..), remoteToUrl)
import Decaf.Client.Internal.Utils (commonAesonOptions, dropTrailing)
import GHC.Generics (Generic)
import qualified Network.HTTP.Client.MultipartFormData as Http.Client
import Network.HTTP.Types (
Header,
QueryText,
Expand Down Expand Up @@ -47,6 +48,7 @@ data DecafRequest = DecafRequest
, decafRequestTrailingSlash :: !Bool
, decafRequestQuery :: !QueryText
, decafRequestPayload :: !(Maybe DecafRequestPayload)
, decafRequestParts :: !(Maybe [Http.Client.Part])
, decafRequestCheckResponse :: !Bool
}

Expand All @@ -66,6 +68,7 @@ instance Show DecafRequest where
, " decafRequestTrailingSlash = " <> show (decafRequestTrailingSlash x)
, " decafRequestQuery = " <> show (decafRequestQuery x)
, " decafRequestPayload = " <> show (decafRequestPayload x)
, " decafRequestParts = " <> maybe "None" (const "Some") (decafRequestParts x)
, " decafRequestCheckResponse = " <> show (decafRequestCheckResponse x)
, "}"
]
Expand Down Expand Up @@ -183,6 +186,7 @@ decafGraphqlQueryNoVars = flip MkDecafGraphqlQuery (Aeson.object [])
-- decafRequestTrailingSlash = False
-- decafRequestQuery = []
-- decafRequestPayload = Nothing
-- decafRequestParts = None
-- decafRequestCheckResponse = True
-- }
initRequest :: DecafRemote -> DecafCredentials -> DecafRequest
Expand All @@ -205,6 +209,7 @@ defaultRequest =
, decafRequestTrailingSlash = False
, decafRequestQuery = []
, decafRequestPayload = Nothing
, decafRequestParts = Nothing
, decafRequestCheckResponse = True
}

Expand Down Expand Up @@ -280,6 +285,7 @@ remote = setRemote
-- decafRequestTrailingSlash = False
-- decafRequestQuery = []
-- decafRequestPayload = Nothing
-- decafRequestParts = None
-- decafRequestCheckResponse = True
-- }
setNamespace :: DecafRequestPath -> DecafRequestCombinator
Expand All @@ -301,6 +307,7 @@ setNamespace n request = request {decafRequestNamespace = n}
-- decafRequestTrailingSlash = False
-- decafRequestQuery = []
-- decafRequestPayload = Nothing
-- decafRequestParts = None
-- decafRequestCheckResponse = True
-- }
namespace :: T.Text -> DecafRequestCombinator
Expand Down Expand Up @@ -495,6 +502,19 @@ noPayload :: DecafRequestCombinator
noPayload = setNoPayload


-- ** Multipart/Form-Data Combinators


-- | Sets multipart/form-data parts for 'DecafRequest'.
setParts :: [Http.Client.Part] -> DecafRequestCombinator
setParts ps request = request {decafRequestParts = Just ps}


-- | Sets no multipart/form-data parts for 'DecafRequest'.
setNoParts :: DecafRequestCombinator
setNoParts request = request {decafRequestParts = Nothing}


-- ** Response Checkers


Expand Down
13 changes: 10 additions & 3 deletions src/Decaf/Client/Internal/Http.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Decaf.Client.DecafRequest (DecafRequest (..), DecafRequestPayload (..), u
import Decaf.Client.DecafResponse (DecafResponse (..))
import Decaf.Client.Internal.Utils (compose)
import GHC.Stack (HasCallStack)
import qualified Network.HTTP.Client.MultipartFormData as Http.Client
import qualified Network.HTTP.Conduit as HC
import qualified Network.HTTP.Simple as HS
import Network.HTTP.Types (Status (statusCode), queryTextToQuery)
Expand Down Expand Up @@ -56,7 +57,7 @@ performDecafRequest
=> DecafRequest
-> m (DecafResponse BL.ByteString)
performDecafRequest request = do
response <- mkResponse <$> (HS.httpLBS (compileRequest request) `catch` throwHttpException request)
response <- mkResponse <$> (HS.httpLBS =<< compileRequest request `catch` throwHttpException request)
when (decafRequestCheckResponse request) (assert2xx response)
pure response

Expand Down Expand Up @@ -118,8 +119,14 @@ type RequestFieldSetter = DecafRequest -> HS.Request -> HS.Request


-- | Compiles a DECAF client 'DecafRequest' into a "http-conduit" 'H.Request'.
compileRequest :: DecafRequest -> HS.Request
compileRequest request = compiler request HS.defaultRequest
compileRequest :: MonadIO m => DecafRequest -> m HS.Request
compileRequest request = do
let bareRequest = compiler request HS.defaultRequest
case decafRequestParts request of
Nothing -> pure bareRequest
Just sp -> do
modifiedRequest <- Http.Client.formDataBody sp bareRequest
pure $ HS.setRequestMethod (BC.pack (show (decafRequestMethod request))) modifiedRequest


-- | Request compiler.
Expand Down

0 comments on commit 1d67806

Please sign in to comment.