diff --git a/gen/amazonka-gen.cabal b/gen/amazonka-gen.cabal index f735ac54ab1..3c91421ee6e 100644 --- a/gen/amazonka-gen.cabal +++ b/gen/amazonka-gen.cabal @@ -95,6 +95,7 @@ library Gen.AST.Data.Field Gen.AST.Data.Instance Gen.AST.Data.Syntax + Gen.AST.Data.Syntax.AWSRequest Gen.AST.Override Gen.AST.Prefix Gen.AST.Subst @@ -124,13 +125,13 @@ library Gen.Types.URI Gen.Types.Waiter Gen.WordFrequency - Paths_amazonka_gen executable gen import: base hs-source-dirs: bin main-is: gen.hs ghc-options: -threaded -rtsopts "-with-rtsopts=-A128m -I0 -qg0" + other-modules: Paths_amazonka_gen build-depends: , amazonka-gen , filepath diff --git a/gen/src/Gen/AST/Data.hs b/gen/src/Gen/AST/Data.hs index bba4c265a76..e9b6df628f0 100644 --- a/gen/src/Gen/AST/Data.hs +++ b/gen/src/Gen/AST/Data.hs @@ -8,6 +8,7 @@ module Gen.AST.Data ) where +import Control.Comonad (extract) import qualified Control.Lens as Lens import qualified Control.Monad.Trans.State as State import qualified Data.ByteString.Char8 as ByteString.Char8 @@ -21,8 +22,9 @@ import qualified Data.Text.Lazy as Text.Lazy import Gen.AST.Data.Field import Gen.AST.Data.Instance import Gen.AST.Data.Syntax as Syntax +import qualified Gen.AST.Data.Syntax.AWSRequest as AWSRequest import Gen.Prelude -import Gen.Types +import Gen.Types hiding (method) import qualified Language.Haskell.Exts as Exts import Language.Haskell.Exts.Pretty (Pretty) @@ -41,7 +43,103 @@ operationData cfg m o = do xis <- addInstances xa xs <$> requestInsts m (_opName o) h xr xs - cls <- pp Print $ requestD cfg m h (xr, xis) (yr, ys) + let requestFunction = method <> format + where + method = methodToText $ _method h + format = + case (mapMaybe fromInstance xis, _method h, m ^. protocol) of + (f : _, _, _) -> f + ([], POST, Query) -> "Query" + ([], POST, EC2) -> "Query" + _ -> "" + fromInstance = \case + ToBody {} -> Just "Body" + ToJSON {} -> Just "JSON" + ToElement {} -> Just "XML" + _ -> Nothing + + responseReceiver + | null ys = AWSRequest.ReceiveNull + | isShared . extract $ yr ^. refAnn, + all fieldBody ys = case m ^. protocol of + APIGateway -> AWSRequest.ReceiveJsonAll + JSON -> AWSRequest.ReceiveJsonAll + RestJSON -> AWSRequest.ReceiveJsonAll + EC2 -> AWSRequest.ReceiveXmlAll wrapper + Query -> AWSRequest.ReceiveXmlAll wrapper + RestXML -> AWSRequest.ReceiveXmlAll wrapper + -- FIXME: take method into account for responses, such as HEAD + -- etc, particuarly when the body might be totally empty. + | any fieldStream ys = + AWSRequest.ReceiveStreamingBody responseFieldParsers + | any fieldLitPayload ys = + AWSRequest.ReceiveBytes responseFieldParsers + | -- Check if we should parse wrapped XML before considering + -- ReceiveEmpty, because fieldBody is false for fields + -- parsed from within wrapped XML. + isXml && isJust wrapper = + AWSRequest.ReceiveXml wrapper responseFieldParsers + | -- Then check for responses that don't use the field body, + -- to avoid trying to `receiveXml` on API calls where AWS + -- might send us an empty body. + not $ any fieldBody ys = + AWSRequest.ReceiveEmpty responseFieldParsers + | -- Finally, check for unwrapped XML, parsed fieldwise. + isXml && isNothing wrapper = + AWSRequest.ReceiveXml wrapper responseFieldParsers + | isJson = + AWSRequest.ReceiveJson responseFieldParsers + | otherwise = + error "Gen.AST.Data.operationData(responseReceiver): don't know how to parse" + where + wrapper = yr ^. refResultWrapper + + isJson = case m ^. protocol of + APIGateway -> True + JSON -> True + RestJSON -> True + EC2 -> False + Query -> False + RestXML -> False + + isXml = case m ^. protocol of + APIGateway -> False + JSON -> False + RestJSON -> False + EC2 -> True + Query -> True + RestXML -> True + + responseFieldParsers = + ys <&> \f -> + case fieldLocation f of + Just Headers -> AWSRequest.ParseHeader hName hParser + where + hName = memberName (m ^. protocol) Output f + hParser = case typeOf f of + TMap {} -> AWSRequest.HeaderFieldMap + TMaybe {} -> AWSRequest.HeaderFieldOptional + _ -> AWSRequest.HeaderFieldRequired + _ -> AWSRequest.FigureTheFieldOut f + + cls <- + pp Print $ + AWSRequest.instanceD + AWSRequest.Config + { requestType = identifier xr, + -- Lookup a specific operationPlugins key before checking + -- for the wildcard. + requestOperationPlugins = + fromMaybe [] $ + (cfg ^. operationPlugins . Lens.at (identifier xr)) + <|> (cfg ^. operationPlugins . Lens.at (mkId "*")), + requestFunction, + responseType = identifier yr, + responseReceiver, + serviceConfig = m ^. serviceConfig + } + (m ^. metadata) + ys mpage <- pagerFields m o >>= traverse (pp Print . pagerD xn) yis' <- renderInsts p yn (responseInsts ys) diff --git a/gen/src/Gen/AST/Data/Field.hs b/gen/src/Gen/AST/Data/Field.hs index 6480790fc84..7db1489dbc3 100644 --- a/gen/src/Gen/AST/Data/Field.hs +++ b/gen/src/Gen/AST/Data/Field.hs @@ -50,13 +50,7 @@ instance TypeOf Field where TList {} -> True _ -> False - isHeader = - fieldLocation f - `elem` map - Just - [ Headers, - Header - ] + isHeader = fieldLocation f == Just Headers ref = f ^. fieldRef typ = fmap unBase64 (typeOf ref) @@ -71,7 +65,7 @@ instance HasInfo Field where -- FIXME: Can just add the metadata to field as well since -- the protocol/timestamp are passed in everywhere in the .Syntax module. mkFields :: - HasMetadata a Identity => + (HasMetadata a Identity) => a -> Solved -> StructF (Shape Solved) -> diff --git a/gen/src/Gen/AST/Data/Instance.hs b/gen/src/Gen/AST/Data/Instance.hs index 95b26ef81d5..cdb07318f34 100644 --- a/gen/src/Gen/AST/Data/Instance.hs +++ b/gen/src/Gen/AST/Data/Instance.hs @@ -20,6 +20,7 @@ data Inst | ToBody Field | IsHashable [Field] | IsNFData [Field] + deriving (Show) instance ToJSON Inst where toJSON = Aeson.toJSON . instToText @@ -91,7 +92,7 @@ responseInsts fs (not . null -> stream, _) = List.partition fieldStream (notLocated fs) requestInsts :: - HasMetadata a f => + (HasMetadata a f) => a -> Id -> HTTP -> @@ -129,7 +130,7 @@ requestInsts m oname h r fs = do where merged xs = let ys = - map Right (satisfies [Querystring] fs) <> xs + map Right (satisfies [QueryString] fs) <> xs ++ map Left protocolQuery in case List.find f is of Just (ToQuery zs) -> ToQuery (ys <> zs) @@ -142,32 +143,32 @@ requestInsts m oname h r fs = do replaceXML is | all nonEmptyXML is = pure $! filter anyXML is | otherwise = - case ( r ^? refXMLNamespace . Lens._Just . xmlUri, - r ^. refLocationName, - listToMaybe (mapMaybe findElement is) - ) of - -- 1. If there's an xmlNamespace and/or locationName on the ref, - -- it should define separate ToXML + ToElement instances - (ns, Just e, _) -> - pure $! ToElement (ns <|> m ^. xmlNamespace) (Left e) : is - -- 2. Otherwise, a single field should be found in the ToXML instance - -- and lifted to a single ToElement instance. - (_, _, Just f) -> - pure $! ToElement ns (Right f) : filter anyXML is - where - ns = - m ^. xmlNamespace - <|> f ^? fieldRef . refXMLNamespace . Lens._Just . xmlUri - - -- 3. Unknown. - (ns, e, _) -> - Left $ - "String determining root ToElement instance: " - ++ Text.unpack (memberId n) - ++ ", namespace: " - ++ show ns - ++ ", locationName: " - ++ show e + case ( r ^? refXMLNamespace . Lens._Just . xmlUri, + r ^. refLocationName, + listToMaybe (mapMaybe findElement is) + ) of + -- 1. If there's an xmlNamespace and/or locationName on the ref, + -- it should define separate ToXML + ToElement instances + (ns, Just e, _) -> + pure $! ToElement (ns <|> m ^. xmlNamespace) (Left e) : is + -- 2. Otherwise, a single field should be found in the ToXML instance + -- and lifted to a single ToElement instance. + (_, _, Just f) -> + pure $! ToElement ns (Right f) : filter anyXML is + where + ns = + m ^. xmlNamespace + <|> f ^? fieldRef . refXMLNamespace . Lens._Just . xmlUri + + -- 3. Unknown. + (ns, e, _) -> + Left $ + "String determining root ToElement instance: " + ++ Text.unpack (memberId n) + ++ ", namespace: " + ++ show ns + ++ ", locationName: " + ++ show e where nonEmptyXML = notXML True anyXML = notXML False @@ -216,7 +217,7 @@ requestInsts m oname h r fs = do v = ("Version", Just version) headers :: [Field] - headers = satisfies [Header, Headers] fs + headers = [f | f <- fs, fieldLocation f == Just Headers] target = (<> ("." <> action)) <$> m ^. targetPrefix diff --git a/gen/src/Gen/AST/Data/Syntax.hs b/gen/src/Gen/AST/Data/Syntax.hs index ab61094ab1c..a05e6d31638 100644 --- a/gen/src/Gen/AST/Data/Syntax.hs +++ b/gen/src/Gen/AST/Data/Syntax.hs @@ -2,7 +2,6 @@ module Gen.AST.Data.Syntax where -import qualified Control.Comonad as Comonad import qualified Control.Lens as Lens import qualified Data.Char as Char import qualified Data.Foldable as Fold @@ -59,15 +58,10 @@ pJE = "Data..:>" pJEMay = "Data..?>" pJEDef = pXDef -pH, pHMay :: QOp -pH = "Data..#" -pHMay = "Data..#?" - -pXMap, pXList, pXList1, pHMap :: Exp +pXMap, pXList, pXList1 :: Exp pXMap = var "Data.parseXMLMap" pXList = var "Data.parseXMLList" pXList1 = var "Data.parseXMLList1" -pHMap = var "Data.parseHeadersMap" toX, toXAttr, toJ, toQ, toH :: QOp toX = "Data.@=" @@ -181,7 +175,6 @@ recordD :: (HasMetadata a Identity) => a -> Id -> [Field] -> QualConDecl recordD m n = conD . \case [] -> Exts.ConDecl () c [] - [x] -> Exts.RecDecl () c [fieldDecl (internal m) x] xs -> Exts.RecDecl () c (map (fieldDecl (internal m)) xs) where fieldDecl h f = Exts.FieldDecl () [ident (fieldAccessor f)] (h f) @@ -353,88 +346,6 @@ notationE' withLensIso = \case TMaybe x -> var "Lens._Just" : lensIso x _other -> [] -requestD :: - (HasMetadata a Identity) => - Config -> - a -> - HTTP -> - (Ref, [Inst]) -> - (Ref, [Field]) -> - Decl -requestD c m h (a, as) (b, bs) = - instD - "Core.AWSRequest" - (identifier a) - $ Just - [ assocD (identifier a) "AWSResponse" (typeId (identifier b)), - funArgsD "request" ["overrides"] (requestF c m h a as), - funD "response" (responseE (m ^. protocol) b bs) - ] - -responseE :: Protocol -> Ref -> [Field] -> Exp -responseE p r fs = Exts.app (responseF p r fs) bdy - where - n = r ^. Lens.to identifier - s = r ^. refAnn . Lens.to Comonad.extract - - bdy :: Exp - bdy - | null fs = var (ctorId n) - | isShared s, all fieldBody fs = lam parseAll - | otherwise = lam . ctorE n $ map parseField fs - - lam :: Exp -> Exp - lam = Exts.lamE [Exts.pvar "s", Exts.pvar "h", Exts.pvar "x"] - - parseField :: Field -> Exp - parseField x = - case fieldLocation x of - Just Headers -> parseHeadersE p x - Just Header -> parseHeadersE p x - Just StatusCode -> parseStatusE x - Just Body | body -> Exts.app pureE (var "x") - Nothing | body -> Exts.app pureE (var "x") - _ -> parseProto x - - parseProto :: Field -> Exp - parseProto f = - case p of - _ | f ^. fieldPayload -> parseOne f - JSON -> parseJSONE p pJE pJEMay pJEDef f - RestJSON -> parseJSONE p pJE pJEMay pJEDef f - APIGateway -> parseJSONE p pJE pJEMay pJEDef f - _ -> parseXMLE p f - - parseOne :: Field -> Exp - parseOne f - | fieldLit f = - if fieldIsParam f - then Exts.app (var "Prelude.pure") (var "x") - else -- Coerce is inserted here to handle newtypes such as Sensitive. - - Exts.app (var "Prelude.pure") - . Exts.paren - . Exts.app justE - . Exts.paren - . Exts.app (var "Prelude.coerce") - $ var "x" - -- This ensures anything which is set as a payload, - -- but is a primitive type is just consumed as a bytestring. - | otherwise = parseAll - - parseAll :: Exp - parseAll = - flip Exts.app (var "x") $ - if any fieldLitPayload fs - then var "Prelude.pure" - else case p of - JSON -> var "Data.eitherParseJSON" - RestJSON -> var "Data.eitherParseJSON" - APIGateway -> var "Data.eitherParseJSON" - _ -> var "Data.parseXML" - - body = any fieldStream fs - instanceD :: Protocol -> Id -> Inst -> Decl instanceD p n = \case FromXML fs -> fromXMLD p n fs @@ -595,9 +506,6 @@ funArgsD f as e = Exts.InsDecl () $ Exts.sfun (ident f) (map ident as) (unguarded e) Exts.noBinds -assocD :: Id -> Text -> Text -> InstDecl -assocD n x y = Exts.InsType () (tyapp (tycon x) (tycon (typeId n))) (tycon y) - decodeD :: Text -> Id -> Text -> ([a] -> Exp) -> [a] -> Decl decodeD c n f dec = instD1 c n . \case @@ -650,22 +558,6 @@ parseJSONE p d dm dd f n = memberName p Output f x = var "x" -parseHeadersE :: Protocol -> Field -> Exp -parseHeadersE p f - | TMap {} <- typeOf f = Exts.appFun pHMap [str n, h] - | fieldMaybe f = decodeE h pHMay n - | otherwise = decodeE h pH n - where - n = memberName p Output f - h = var "h" - -parseStatusE :: Field -> Exp -parseStatusE f - | fieldMaybe f = Exts.app pureE (Exts.app justE v) - | otherwise = Exts.app pureE v - where - v = Exts.paren $ Exts.app (var "Prelude.fromEnum") (var "s") - toXMLE :: Protocol -> Field -> Exp toXMLE p f = toGenericE p opX "Data.toXML" toXMap toXList f where @@ -786,65 +678,6 @@ inputNames, outputNames :: Protocol -> Field -> Names inputNames p f = Proto.nestedNames p Input (f ^. fieldId) (f ^. fieldRef) outputNames p f = Proto.nestedNames p Output (f ^. fieldId) (f ^. fieldRef) -requestF :: - (HasMetadata a Identity) => - Config -> - a -> - HTTP -> - Ref -> - [Inst] -> - Exp -requestF c meta h r is = - maybe e (foldr applyPlugin e) selectedPlugins - where - applyPlugin x = - -- Plugin functions are of the form :: Request a -> Request a - Exts.infixApp (var x) "Prelude.." - - selectedPlugins = - -- Lookup a specific operationPlugins key before the wildcard. - HashMap.lookup (identifier r) (c ^. operationPlugins) - <|> HashMap.lookup (mkId "*") (c ^. operationPlugins) - - e = Exts.app v (Exts.app (var "overrides") (var $ meta ^. serviceConfig)) - - v = - var - . mappend ("Request." <> methodToText m) - . fromMaybe mempty - . listToMaybe - $ mapMaybe f is - - f = \case - ToBody {} -> Just "Body" - ToJSON {} -> Just "JSON" - ToElement {} -> Just "XML" - _ - | p == Query, - m == POST -> - Just "Query" - _ - | p == EC2, - m == POST -> - Just "Query" - _ -> Nothing - - m = h ^. method - p = meta ^. protocol - --- FIXME: take method into account for responses, such as HEAD etc, particuarly --- when the body might be totally empty. -responseF :: Protocol -> RefF a -> [Field] -> Exp -responseF p r fs - | null fs = var "Response.receiveNull" - | any fieldStream fs = var "Response.receiveBody" - | any fieldLitPayload fs = var "Response.receiveBytes" - | Just x <- r ^. refResultWrapper = Exts.app (var (suf <> "Wrapper")) (str x) - | not $ any fieldBody fs = var "Response.receiveEmpty" - | otherwise = var suf - where - suf = "Response.receive" <> Proto.suffix p - waiterS :: Id -> Waiter a -> Decl waiterS n w = Exts.TypeSig () [ident c] $ tyapp (tycon "Core.Wait") (tycon k) where diff --git a/gen/src/Gen/AST/Data/Syntax/AWSRequest.hs b/gen/src/Gen/AST/Data/Syntax/AWSRequest.hs new file mode 100644 index 00000000000..391e5e53a5b --- /dev/null +++ b/gen/src/Gen/AST/Data/Syntax/AWSRequest.hs @@ -0,0 +1,231 @@ +module Gen.AST.Data.Syntax.AWSRequest + ( instanceD, + Config (..), + ResponseReceiver (..), + ResponseFieldParser (..), + HeaderFieldParser (..), + ) +where + +import Gen.AST.Data.Field (Field, fieldIsParam, fieldLit, fieldLitPayload, fieldLocation, fieldPayload, fieldStream) +import Gen.AST.Data.Syntax + ( ctorE, + funArgsD, + funD, + instD, + justE, + pJE, + pJEDef, + pJEMay, + parseJSONE, + parseXMLE, + pureE, + str, + tyapp, + tycon, + var, + ) +import Gen.Prelude +import Gen.Types hiding (Config, serviceConfig) +import qualified Language.Haskell.Exts as Exts + +data Config = Config + { -- | Name of the data type we generate to represent the input + -- shape from botocore. + requestType :: Id, + -- | Name of the request function to call (@putBody@, @postQuery@, ...). + -- from the @"Request"@ module. + requestFunction :: Text, + -- | List of function names to apply to the computed request in + -- the implementation of the @request@ function. + requestOperationPlugins :: [Text], + -- | Name of the data type we generate for the botocore output + -- shape that corresponds to 'requestType'. + responseType :: Id, + -- | How to receive and parse the response from AWS. + responseReceiver :: ResponseReceiver, + -- | Name of the service config value to use by default. As of + -- 2025-11, always @"defaultService"@; the parser for 'Metadata' + -- would override the service abbrev in all cases. + serviceConfig :: Text + } + deriving (Show) + +-- | Which Amazonka function should be used to parse AWS's response to +-- an API call, and additional arguments are necessary to actually +-- perform the parse. +data ResponseReceiver + = -- | Perform no parsing and return an empty response using + -- @receiveNull@. The response constructor in 'responseType' must + -- take no arguments. + ReceiveNull + | -- | Parse the entire response as JSON using @receiveJSON@. + ReceiveJsonAll + | -- | Parse the entire response as (optionally wrapped) XML, using + -- @receiveXML@ or @receiveXMLWrapper@. + ReceiveXmlAll (Maybe Text) + | -- | Parse a streaming response from AWS using @receiveStreamingBody@. + ReceiveStreamingBody [ResponseFieldParser] + | -- | Parse a response from AWS, accepting the body as an unparsed + -- 'ByteString'. Uses @receiveBytes@. + ReceiveBytes [ResponseFieldParser] + | -- | Parse a JSON response from AWS fieldwise using @receiveJSON@. + ReceiveJson [ResponseFieldParser] + | -- | Parse (optionally wrapped) XML response fieldwise using either + -- @receiveXML@ or @receiveXMLWrapper@. + ReceiveXml (Maybe Text) [ResponseFieldParser] + | -- | Parse an empty response using @receiveEmpty@. The body will + -- not be available to parse and all fields will come from headers + -- or status. + ReceiveEmpty [ResponseFieldParser] + deriving (Show) + +-- | How to generate the parser for a single field, for response +-- parsers which do per-field parsing. +data ResponseFieldParser + = -- | Parse the repsonse field from the HTTP response headers named + -- like the given 'Text'. + ParseHeader Text HeaderFieldParser + | FigureTheFieldOut Field + deriving (Show) + +-- | How to parse a single field from the HTTP response headers. +-- +-- A 'HeaderFieldParser' does not parse a single header, because some +-- AWS services represent structured data by breaking it across +-- multiple similarly-named headers. +data HeaderFieldParser + = -- | Parse a required field from headers using @(.#)@. + HeaderFieldRequired + | -- | Parse an optional field from headers using @(.#?)@. + HeaderFieldOptional + | -- | Parse a map field from headers using @parseHeadersMap@. + HeaderFieldMap + deriving (Show) + +instanceD :: + Config -> + Metadata f -> + [Field] -> + Exts.Decl () +instanceD c@Config {requestType} m responseFields = + instD "Core.AWSRequest" requestType $ + Just + [ awsResponseD c, + requestD c, + funD "response" (responseE c (m ^. protocol) responseFields) + ] + +awsResponseD :: Config -> Exts.InstDecl () +awsResponseD Config {..} = + Exts.InsType + () + (tycon "AWSResponse" `tyapp` tycon (typeId requestType)) + (tycon (typeId responseType)) + +requestD :: Config -> Exts.InstDecl () +requestD Config {..} = + funArgsD "request" ["overrides"] $ foldr applyPlugin e requestOperationPlugins + where + -- Plugin functions are of the form :: Request a -> Request a + applyPlugin x = Exts.infixApp (var x) "Prelude.." + + e = + Exts.app + (var $ "Request." <> requestFunction) + (Exts.app (var "overrides") (var serviceConfig)) + +responseE :: Config -> Protocol -> [Field] -> Exts.Exp () +responseE Config {..} p fs = + case responseReceiver of + ReceiveNull -> + var "Response.receiveNull" `Exts.app` var (ctorId responseType) + ReceiveJsonAll -> + var "Response.receiveJSON" + `Exts.app` lam (var "Data.eitherParseJSON" `Exts.app` var "x") + ReceiveXmlAll Nothing -> + var "Response.receiveXML" + `Exts.app` lam (var "Data.parseXML" `Exts.app` var "x") + ReceiveXmlAll (Just wrapper) -> + var "Response.receiveXMLWrapper" + `Exts.app` str wrapper + `Exts.app` lam (var "Data.parseXML" `Exts.app` var "x") + ReceiveStreamingBody fieldParsers -> + var "Response.receiveStreamingBody" + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + ReceiveBytes fieldParsers -> + var "Response.receiveBytes" + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + ReceiveJson fieldParsers -> + var "Response.receiveJSON" + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + ReceiveXml Nothing fieldParsers -> + var "Response.receiveXML" + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + ReceiveXml (Just wrapper) fieldParsers -> + var "Response.receiveXMLWrapper" + `Exts.app` str wrapper + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + ReceiveEmpty fieldParsers -> + var "Response.receiveEmpty" + `Exts.app` lam (ctorE responseType $ map parseField fieldParsers) + where + lam :: Exts.Exp () -> Exts.Exp () + lam = Exts.lamE [Exts.pvar "s", Exts.pvar "h", Exts.pvar "x"] + + parseField :: ResponseFieldParser -> Exts.Exp () + parseField = \case + ParseHeader hName hField -> case hField of + HeaderFieldRequired -> Exts.infixApp (var "h") "Data..#" (str hName) + HeaderFieldOptional -> Exts.infixApp (var "h") "Data..#?" (str hName) + HeaderFieldMap -> + Exts.appFun (var "Data.parseHeadersMap") [str hName, var "h"] + FigureTheFieldOut field -> parseField' field + + parseField' :: Field -> Exts.Exp () + parseField' x = + case fieldLocation x of + Just StatusCode -> + pureE `Exts.app` Exts.paren (var "Prelude.fromEnum" `Exts.app` var "s") + Just Body | body -> Exts.app pureE (var "x") + Nothing | body -> Exts.app pureE (var "x") + _ -> parseProto x + + parseProto :: Field -> Exts.Exp () + parseProto f = + case p of + _ | f ^. fieldPayload -> parseOne f + JSON -> parseJSONE p pJE pJEMay pJEDef f + RestJSON -> parseJSONE p pJE pJEMay pJEDef f + APIGateway -> parseJSONE p pJE pJEMay pJEDef f + _ -> parseXMLE p f + + parseOne :: Field -> Exts.Exp () + parseOne f + | fieldLit f = + if fieldIsParam f + then Exts.app (var "Prelude.pure") (var "x") + else -- Coerce is inserted here to handle newtypes such as Sensitive. + + Exts.app (var "Prelude.pure") + . Exts.paren + . Exts.app justE + . Exts.paren + . Exts.app (var "Prelude.coerce") + $ var "x" + -- This ensures anything which is set as a payload, + -- but is a primitive type is just consumed as a bytestring. + | otherwise = parseAll + + parseAll :: Exts.Exp () + parseAll = + flip Exts.app (var "x") $ + if any fieldLitPayload fs + then var "Prelude.pure" + else case p of + JSON -> var "Data.eitherParseJSON" + RestJSON -> var "Data.eitherParseJSON" + APIGateway -> var "Data.eitherParseJSON" + _ -> var "Data.parseXML" + + body = any fieldStream fs diff --git a/gen/src/Gen/Types/Service.hs b/gen/src/Gen/Types/Service.hs index e878c323d4f..03acbcf93d3 100644 --- a/gen/src/Gen/Types/Service.hs +++ b/gen/src/Gen/Types/Service.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE TemplateHaskell #-} module Gen.Types.Service where @@ -96,18 +97,22 @@ instance ToJSON Checksum where data Location = Headers - | Header | Uri - | Querystring + | QueryString | StatusCode - | Body + | -- | Not present in @botocore@, but we explicitly annotate fields + -- with it. + Body deriving stock (Eq, Show, Generic) instance FromJSON Location where - parseJSON = gParseJSON' camel - -instance ToJSON Location where - toJSON = gToJSON' camel + parseJSON = Aeson.withText "Location" $ \t -> case t of + "header" -> pure Headers -- Present in e.g. accessanalyzer + "headers" -> pure Headers -- Present in e.g. dataexchange + "querystring" -> pure QueryString + "statusCode" -> pure StatusCode + "uri" -> pure Uri + _ -> fail $ "Unknown location: " <> show t data XML = XML' { _xmlPrefix :: Maybe Text, @@ -141,17 +146,18 @@ instance HasId (RefF a) where identifier = identifier . _refShape instance FromJSON (RefF ()) where - parseJSON = Aeson.withObject "ref" $ \o -> - RefF () - <$> o .: "shape" - <*> o .:? "documentation" - <*> o .:? "location" - <*> o .:? "locationName" - <*> o .:? "resultWrapper" - <*> o .:? "queryName" - <*> o .:? "streaming" .!= False - <*> o .:? "xmlAttribute" .!= False - <*> o .:? "xmlNamespace" + parseJSON = Aeson.withObject "ref" $ \o -> do + let _refAnn = () + _refShape <- o .: "shape" + _refDocumentation <- o .:? "documentation" + _refLocation <- o .:? "location" + _refLocationName <- o .:? "locationName" + _refResultWrapper <- o .:? "resultWrapper" + _refQueryName <- o .:? "queryName" + _refStreaming <- o .:? "streaming" .!= False + _refXMLAttribute <- o .:? "xmlAttribute" .!= False + _refXMLNamespace <- o .:? "xmlNamespace" + pure RefF {..} class HasRefs f where references :: Lens.Traversal (f a) (f b) (RefF a) (RefF b) @@ -198,7 +204,7 @@ instance FromJSON Info where <*> o .:? "exception" .!= False <*> o .:? "error" -nonEmpty :: HasInfo a => a -> Bool +nonEmpty :: (HasInfo a) => a -> Bool nonEmpty = (> Just 0) . Lens.view infoMin data ListF a = ListF @@ -354,7 +360,7 @@ $(Lens.makeLenses ''Operation) operationNS :: NS -> Id -> NS operationNS ns = mappend ns . mkNS . typeId -inputName, outputName :: HasId a => Operation Identity a b -> Id +inputName, outputName :: (HasId a) => Operation Identity a b -> Id inputName = identifier . Lens.view (opInput . _Identity) outputName = identifier . Lens.view (opOutput . _Identity) @@ -372,7 +378,7 @@ instance FromJSON (Operation Maybe (RefF ()) ()) where <*> o .:? "output" <*> pure Nothing -instance ToJSON a => ToJSON (Operation Identity a b) where +instance (ToJSON a) => ToJSON (Operation Identity a b) where toJSON o = Aeson.object [ "name" .= (o ^. opName), @@ -405,25 +411,25 @@ deriving instance Show (Metadata Identity) $(Lens.makeClassy ''Metadata) instance FromJSON (Metadata Maybe) where - parseJSON = Aeson.withObject "meta" $ \o -> - Metadata - <$> o .: "protocol" - <*> o .: "serviceAbbreviation" - <*> (o .: "serviceAbbreviation" <&> renameServiceFunction) - <*> (o .: "serviceFullName" <&> renameService) - <*> (o .: "signingName" <|> o .: "endpointPrefix") - <*> o .: "apiVersion" - <*> o .: "signatureVersion" - <*> o .: "endpointPrefix" - <*> o .:? "checksumFormat" - <*> o .:? "xmlNamespace" - <*> o .:? "jsonVersion" - <*> o .:? "targetPrefix" + parseJSON = Aeson.withObject "meta" $ \o -> do + _protocol <- o .: "protocol" + _serviceAbbrev <- o .: "serviceAbbreviation" + _serviceConfig <- o .: "serviceAbbreviation" <&> renameServiceFunction + _serviceFullName <- o .: "serviceFullName" <&> renameService + _signingName <- o .: "signingName" <|> o .: "endpointPrefix" + _apiVersion <- o .: "apiVersion" + _signatureVersion <- o .: "signatureVersion" + _endpointPrefix <- o .: "endpointPrefix" + _checksumFormat <- o .:? "checksumFormat" + _xmlNamespace <- o .:? "xmlNamespace" + _jsonVersion <- o .:? "jsonVersion" + _targetPrefix <- o .:? "targetPrefix" + pure Metadata {..} instance ToJSON (Metadata Identity) where toJSON = gToJSON' camel -serviceError :: HasMetadata a f => a -> Text +serviceError :: (HasMetadata a f) => a -> Text serviceError m = case m ^. protocol of JSON -> "parseJSONError" @@ -472,7 +478,7 @@ type Ref = RefF (Shape Solved) class IsStreaming a where isStreaming :: a -> Bool - default isStreaming :: HasInfo a => a -> Bool + default isStreaming :: (HasInfo a) => a -> Bool isStreaming = Lens.view infoStreaming instance IsStreaming Info @@ -483,7 +489,7 @@ instance IsStreaming (ShapeF a) instance IsStreaming (Shape a) -instance IsStreaming a => IsStreaming (RefF a) where +instance (IsStreaming a) => IsStreaming (RefF a) where isStreaming r = _refStreaming r || isStreaming (_refAnn r) instance IsStreaming TType where diff --git a/lib/amazonka-core/src/Amazonka/Response.hs b/lib/amazonka-core/src/Amazonka/Response.hs index 442db1a7dff..eec55875c6f 100644 --- a/lib/amazonka-core/src/Amazonka/Response.hs +++ b/lib/amazonka-core/src/Amazonka/Response.hs @@ -10,10 +10,11 @@ -- the connection. This is needed to avoid hitting this issue: -- . -- --- The only exception is 'receiveBody', which passes a streaming response --- body to a callback and thus is not allowed to close the connection. Users --- of streaming functions are advised to be careful and consume the response --- body manually if they want the connection to be closed promptly. +-- The only exception is 'receiveStreamingBody', which passes a streaming +-- response body to a callback and thus is not allowed to close the +-- connection. Users of streaming functions are advised to be careful and +-- consume the response body manually if they want the connection to be closed +-- promptly. -- -- Note that using 'runResourceT' will always close the connection. module Amazonka.Response @@ -24,6 +25,7 @@ module Amazonka.Response receiveJSON, receiveBytes, receiveBody, + receiveStreamingBody, ) where @@ -43,7 +45,7 @@ import Network.HTTP.Types (ResponseHeaders) import qualified Text.XML as XML receiveNull :: - MonadResource m => + (MonadResource m) => AWSResponse a -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> @@ -55,7 +57,7 @@ receiveNull rs _ = liftIO (Client.responseClose r) $> Right rs receiveEmpty :: - MonadResource m => + (MonadResource m) => (Int -> ResponseHeaders -> () -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> @@ -67,7 +69,7 @@ receiveEmpty f _ = liftIO (Client.responseClose r) $> f s h () receiveXMLWrapper :: - MonadResource m => + (MonadResource m) => Text -> (Int -> ResponseHeaders -> [XML.Node] -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> @@ -78,7 +80,7 @@ receiveXMLWrapper :: receiveXMLWrapper n f = receiveXML (\s h x -> x .@ n >>= f s h) receiveXML :: - MonadResource m => + (MonadResource m) => (Int -> ResponseHeaders -> [XML.Node] -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> @@ -88,7 +90,7 @@ receiveXML :: receiveXML = deserialise decodeXML receiveJSON :: - MonadResource m => + (MonadResource m) => (Int -> ResponseHeaders -> Aeson.Object -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> @@ -98,7 +100,7 @@ receiveJSON :: receiveJSON = deserialise Aeson.eitherDecode' receiveBytes :: - MonadResource m => + (MonadResource m) => (Int -> ResponseHeaders -> ByteString -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> @@ -107,21 +109,33 @@ receiveBytes :: m (Either Error (ClientResponse (AWSResponse a))) receiveBytes = deserialise (Right . LBS.toStrict) +-- | Deprecated alias for 'receiveStreamingBody'. receiveBody :: - MonadResource m => + (MonadResource m) => (Int -> ResponseHeaders -> ResponseBody -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> Service -> Proxy a -> ClientResponse ClientBody -> m (Either Error (ClientResponse (AWSResponse a))) -receiveBody f _ = +receiveBody = receiveStreamingBody +{-# DEPRECATED receiveBody "this function will be removed in Amazonka 2.2" #-} + +receiveStreamingBody :: + (MonadResource m) => + (Int -> ResponseHeaders -> ResponseBody -> Either String (AWSResponse a)) -> + (ByteStringLazy -> IO ByteStringLazy) -> + Service -> + Proxy a -> + ClientResponse ClientBody -> + m (Either Error (ClientResponse (AWSResponse a))) +receiveStreamingBody f _ = stream $ \_ s h x -> pure (f s h (ResponseBody x)) -- | Deserialise an entire response body, such as an XML or JSON payload. deserialise :: - MonadResource m => + (MonadResource m) => (ByteStringLazy -> Either String b) -> (Int -> ResponseHeaders -> b -> Either String (AWSResponse a)) -> (ByteStringLazy -> IO ByteStringLazy) -> @@ -146,7 +160,7 @@ deserialise reader parser responseBodyHook Service {..} _ rs = -- | Stream a raw response body, such as an S3 object payload. stream :: - MonadResource m => + (MonadResource m) => ( ClientResponse () -> Int -> ResponseHeaders -> @@ -173,5 +187,5 @@ stream parser Service {..} _ rs = Except.throwE $ SerializeError (SerializeError' abbrev status Nothing err) -sinkLBS :: MonadResource m => ClientBody -> m ByteStringLazy +sinkLBS :: (MonadResource m) => ClientBody -> m ByteStringLazy sinkLBS bdy = liftResourceT (bdy `Conduit.connect` Conduit.Binary.sinkLbs) diff --git a/lib/amazonka-core/src/Amazonka/Types.hs b/lib/amazonka-core/src/Amazonka/Types.hs index be0b3a63b43..20501dfac03 100644 --- a/lib/amazonka-core/src/Amazonka/Types.hs +++ b/lib/amazonka-core/src/Amazonka/Types.hs @@ -677,6 +677,17 @@ class (Typeable a, Typeable (AWSResponse a)) => AWSRequest a where ClientResponse ClientBody -> m (Either Error (ClientResponse (AWSResponse a))) + -- | For some requests, botocore will designate one field of a + -- request as an "idempotency token", which the caller can manually + -- fill in to defend against deduplication. If he does not, it needs + -- to be filled in by the SDK. + -- + -- This is a 'Lens.LensLike'' and not a true 'Lens.Lens'' because if + -- the request type does not contain an idempotency token, it will + -- do nothing (violating the get/set law). + updateIdempotencyToken :: + (Functor f) => Lens.LensLike' f a (Maybe Text) + -- | An access key ID. -- -- For example: @AKIAIOSFODNN7EXAMPLE@ @@ -952,7 +963,6 @@ pattern TelAviv = Region' "il-central-1" pattern MexicoCentral :: Region pattern MexicoCentral = Region' "mx-central-1" - -- Middle East pattern Bahrain :: Region diff --git a/lib/amazonka-core/test/Test/Amazonka/Sign/V4.hs b/lib/amazonka-core/test/Test/Amazonka/Sign/V4.hs index 287228bd460..c0f00a2496c 100644 --- a/lib/amazonka-core/test/Test/Amazonka/Sign/V4.hs +++ b/lib/amazonka-core/test/Test/Amazonka/Sign/V4.hs @@ -1,5 +1,5 @@ -- | --- Module : Test.Amazonka.Sign.V$ +-- Module : Test.Amazonka.Sign.V4 -- Copyright : (c) 2013-2023 Brendan Hay -- License : Mozilla Public License, v. 2.0. -- Maintainer : Brendan Hay diff --git a/lib/amazonka/CHANGELOG.md b/lib/amazonka/CHANGELOG.md index 8ba53a67423..d7ab040e716 100644 --- a/lib/amazonka/CHANGELOG.md +++ b/lib/amazonka/CHANGELOG.md @@ -4,6 +4,9 @@ ### Changed +- `amazonka` will now store idempotency tokens into requests that support them but have not been set by the caller. + - `amazonka-core`: Class `AWSRequest` has an new function `updateIdempotencyToken`. If a request type can contain an idempotency token, this function will allow it to be updated. + - `amazonka`: Improve error handling during periodic credential refresh in `fetchAuthInBackground`. Exceptions thrown by the refresh action are now categorized and rethrown to the parent thread as `RetrievalError`, `AuthServiceError`, or `OtherAuthError` (instead of just `RetrievalError` which was a bug). (thanks @kushagarr) @@ -119,7 +122,8 @@ [\#955](https://github.com/brendanhay/amazonka/pull/955) - `amazonka-core`: Support Cloudflare R2 by adjusting which headers get signed [\#977](https://github.com/brendanhay/amazonka/pull/977) - +- `amazonka-core`: `Amazonka.Response.receiveBody` has been renamed to `Amazonka.Response.receiveStreamingBody`. This is an internal function used in service bindings and should not affect normal users. `Amazonka.Response.receiveBody` will remain as a deprecated alias until Amazonka 2.2. +[\#???](https://github.com/brendanhay/amazonka/pull/???) ## [2.0.0](https://github.com/brendanhay/amazonka/tree/2.0.0) Released: **28 July 2023**, Compare: [2.0.0-rc2](https://github.com/brendanhay/amazonka/compare/2.0.0-rc2...2.0.0) diff --git a/lib/amazonka/src/Amazonka/HTTP.hs b/lib/amazonka/src/Amazonka/HTTP.hs index 8640ff0f6fa..0d81058be05 100644 --- a/lib/amazonka/src/Amazonka/HTTP.hs +++ b/lib/amazonka/src/Amazonka/HTTP.hs @@ -28,6 +28,8 @@ import Control.Monad.Trans.Resource (liftResourceT, transResourceT) import qualified Control.Retry as Retry import Data.Foldable (traverse_) import qualified Data.Time as Time +import qualified Data.UUID as UUID +import qualified Data.UUID.V4 as UUIDv4 import qualified Network.HTTP.Conduit as Client.Conduit retryRequest :: @@ -152,10 +154,16 @@ httpRequest env@Env {hooks, manager, region} cfgRq = -- (Request a). configureRequest :: (AWSRequest a, MonadIO m) => Env' withAuth -> a -> m (Request a) -configureRequest env@Env {overrides, hooks} = - liftIO - . Hooks.configuredRequest hooks env - . request overrides +configureRequest env@Env {overrides, hooks} awsRequest = do + -- If the idempotency token is not set, create a v4 UUID + -- for consistency with botocore: + -- https://github.com/boto/botocore/blob/1122d80bfeb3a52a7ae7138a9e9abdb538eae895/botocore/handlers.py#L285 + let uuidV4IfAbsent = \case + Nothing -> liftIO $ Just . UUID.toText <$> UUIDv4.nextRandom + Just token -> pure $ Just token + configuredRequest <- + request overrides <$> updateIdempotencyToken uuidV4IfAbsent awsRequest + liftIO $ Hooks.configuredRequest hooks env configuredRequest retryStream :: Request a -> Retry.RetryPolicy retryStream Request {body} = diff --git a/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetChunk.hs b/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetChunk.hs index f502be11f54..25420c204ce 100644 --- a/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetChunk.hs +++ b/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetChunk.hs @@ -96,7 +96,7 @@ instance Core.AWSRequest GetChunk where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetChunkResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s)) diff --git a/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetObjectMetadata.hs b/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetObjectMetadata.hs index 81763f91650..dc208250fbc 100644 --- a/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetObjectMetadata.hs +++ b/lib/services/amazonka-backupstorage/gen/Amazonka/BackupStorage/GetObjectMetadata.hs @@ -99,7 +99,7 @@ instance Core.AWSRequest GetObjectMetadata where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetObjectMetadataResponse' Prelude.<$> (h Data..#? "x-amz-checksum") diff --git a/lib/services/amazonka-codeartifact/gen/Amazonka/CodeArtifact/GetPackageVersionAsset.hs b/lib/services/amazonka-codeartifact/gen/Amazonka/CodeArtifact/GetPackageVersionAsset.hs index ea3e50f4d85..238c8d80aeb 100644 --- a/lib/services/amazonka-codeartifact/gen/Amazonka/CodeArtifact/GetPackageVersionAsset.hs +++ b/lib/services/amazonka-codeartifact/gen/Amazonka/CodeArtifact/GetPackageVersionAsset.hs @@ -230,7 +230,7 @@ instance Core.AWSRequest GetPackageVersionAsset where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetPackageVersionAssetResponse' Prelude.<$> (h Data..#? "X-AssetName") diff --git a/lib/services/amazonka-ebs/gen/Amazonka/EBS/GetSnapshotBlock.hs b/lib/services/amazonka-ebs/gen/Amazonka/EBS/GetSnapshotBlock.hs index 3bda84a6af5..e77ad0d8d93 100644 --- a/lib/services/amazonka-ebs/gen/Amazonka/EBS/GetSnapshotBlock.hs +++ b/lib/services/amazonka-ebs/gen/Amazonka/EBS/GetSnapshotBlock.hs @@ -149,7 +149,7 @@ instance Core.AWSRequest GetSnapshotBlock where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetSnapshotBlockResponse' Prelude.<$> (h Data..#? "x-amz-Checksum") diff --git a/lib/services/amazonka-glacier/gen/Amazonka/Glacier/GetJobOutput.hs b/lib/services/amazonka-glacier/gen/Amazonka/Glacier/GetJobOutput.hs index ad091371bf9..e686f3889f4 100644 --- a/lib/services/amazonka-glacier/gen/Amazonka/Glacier/GetJobOutput.hs +++ b/lib/services/amazonka-glacier/gen/Amazonka/Glacier/GetJobOutput.hs @@ -271,7 +271,7 @@ instance Core.AWSRequest GetJobOutput where Request.glacierVersionHeader (Core.version defaultService) Prelude.. Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetJobOutputResponse' Prelude.<$> (h Data..#? "Accept-Ranges") diff --git a/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetClip.hs b/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetClip.hs index 6b9d924f421..e9a11f735f5 100644 --- a/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetClip.hs +++ b/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetClip.hs @@ -159,7 +159,7 @@ instance Core.AWSRequest GetClip where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetClipResponse' Prelude.<$> (h Data..#? "Content-Type") diff --git a/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetMediaForFragmentList.hs b/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetMediaForFragmentList.hs index 48d493b668b..e399361ade5 100644 --- a/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetMediaForFragmentList.hs +++ b/lib/services/amazonka-kinesis-video-archived-media/gen/Amazonka/KinesisVideoArchivedMedia/GetMediaForFragmentList.hs @@ -146,7 +146,7 @@ instance Core.AWSRequest GetMediaForFragmentList where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetMediaForFragmentListResponse' Prelude.<$> (h Data..#? "Content-Type") diff --git a/lib/services/amazonka-kinesis-video-media/gen/Amazonka/KinesisVideoMedia/GetMedia.hs b/lib/services/amazonka-kinesis-video-media/gen/Amazonka/KinesisVideoMedia/GetMedia.hs index 3df189de94b..3b01f71d818 100644 --- a/lib/services/amazonka-kinesis-video-media/gen/Amazonka/KinesisVideoMedia/GetMedia.hs +++ b/lib/services/amazonka-kinesis-video-media/gen/Amazonka/KinesisVideoMedia/GetMedia.hs @@ -154,7 +154,7 @@ instance Core.AWSRequest GetMedia where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetMediaResponse' Prelude.<$> (h Data..#? "Content-Type") diff --git a/lib/services/amazonka-lakeformation/gen/Amazonka/LakeFormation/GetWorkUnitResults.hs b/lib/services/amazonka-lakeformation/gen/Amazonka/LakeFormation/GetWorkUnitResults.hs index ca2c6da7031..f2718d5f423 100644 --- a/lib/services/amazonka-lakeformation/gen/Amazonka/LakeFormation/GetWorkUnitResults.hs +++ b/lib/services/amazonka-lakeformation/gen/Amazonka/LakeFormation/GetWorkUnitResults.hs @@ -121,7 +121,7 @@ instance Core.AWSRequest GetWorkUnitResults where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetWorkUnitResultsResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s)) diff --git a/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PostContent.hs b/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PostContent.hs index 80edcb506a8..74429b506e3 100644 --- a/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PostContent.hs +++ b/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PostContent.hs @@ -553,7 +553,7 @@ instance Core.AWSRequest PostContent where request overrides = Request.postBody (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> PostContentResponse' Prelude.<$> (h Data..#? "x-amz-lex-active-contexts") diff --git a/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PutSession.hs b/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PutSession.hs index 0904a178b8f..613b8c1f6db 100644 --- a/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PutSession.hs +++ b/lib/services/amazonka-lex-runtime/gen/Amazonka/LexRuntime/PutSession.hs @@ -333,7 +333,7 @@ instance Core.AWSRequest PutSession where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> PutSessionResponse' Prelude.<$> (h Data..#? "x-amz-lex-active-contexts") diff --git a/lib/services/amazonka-medialive/gen/Amazonka/MediaLive/DescribeInputDeviceThumbnail.hs b/lib/services/amazonka-medialive/gen/Amazonka/MediaLive/DescribeInputDeviceThumbnail.hs index c479891f1d5..061fbd2ea85 100644 --- a/lib/services/amazonka-medialive/gen/Amazonka/MediaLive/DescribeInputDeviceThumbnail.hs +++ b/lib/services/amazonka-medialive/gen/Amazonka/MediaLive/DescribeInputDeviceThumbnail.hs @@ -104,7 +104,7 @@ instance Core.AWSRequest DescribeInputDeviceThumbnail where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> DescribeInputDeviceThumbnailResponse' Prelude.<$> (h Data..#? "Content-Length") diff --git a/lib/services/amazonka-mediastore-dataplane/gen/Amazonka/MediaStoreData/GetObject.hs b/lib/services/amazonka-mediastore-dataplane/gen/Amazonka/MediaStoreData/GetObject.hs index 956d0656049..8e65c35cb66 100644 --- a/lib/services/amazonka-mediastore-dataplane/gen/Amazonka/MediaStoreData/GetObject.hs +++ b/lib/services/amazonka-mediastore-dataplane/gen/Amazonka/MediaStoreData/GetObject.hs @@ -183,7 +183,7 @@ instance Core.AWSRequest GetObject where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetObjectResponse' Prelude.<$> (h Data..#? "Cache-Control") diff --git a/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReadSet.hs b/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReadSet.hs index 810c507a495..1452a969b45 100644 --- a/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReadSet.hs +++ b/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReadSet.hs @@ -115,7 +115,7 @@ instance Core.AWSRequest GetReadSet where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetReadSetResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s)) diff --git a/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReference.hs b/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReference.hs index fd2d64fd27b..707906bdec4 100644 --- a/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReference.hs +++ b/lib/services/amazonka-omics/gen/Amazonka/Omics/GetReference.hs @@ -125,7 +125,7 @@ instance Core.AWSRequest GetReference where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetReferenceResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s)) diff --git a/lib/services/amazonka-polly/gen/Amazonka/Polly/SynthesizeSpeech.hs b/lib/services/amazonka-polly/gen/Amazonka/Polly/SynthesizeSpeech.hs index 04fd2fd6dba..6c5e0831cc1 100644 --- a/lib/services/amazonka-polly/gen/Amazonka/Polly/SynthesizeSpeech.hs +++ b/lib/services/amazonka-polly/gen/Amazonka/Polly/SynthesizeSpeech.hs @@ -333,7 +333,7 @@ instance Core.AWSRequest SynthesizeSpeech where request overrides = Request.postJSON (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> SynthesizeSpeechResponse' Prelude.<$> (h Data..#? "Content-Type") diff --git a/lib/services/amazonka-s3/gen/Amazonka/S3/GetObject.hs b/lib/services/amazonka-s3/gen/Amazonka/S3/GetObject.hs index 1cef8bc552d..50efcfdc12c 100644 --- a/lib/services/amazonka-s3/gen/Amazonka/S3/GetObject.hs +++ b/lib/services/amazonka-s3/gen/Amazonka/S3/GetObject.hs @@ -585,7 +585,7 @@ instance Core.AWSRequest GetObject where Request.s3vhost Prelude.. Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetObjectResponse' Prelude.<$> (h Data..#? "accept-ranges") diff --git a/lib/services/amazonka-s3/gen/Amazonka/S3/GetObjectTorrent.hs b/lib/services/amazonka-s3/gen/Amazonka/S3/GetObjectTorrent.hs index c1227f44cfc..68a36abd064 100644 --- a/lib/services/amazonka-s3/gen/Amazonka/S3/GetObjectTorrent.hs +++ b/lib/services/amazonka-s3/gen/Amazonka/S3/GetObjectTorrent.hs @@ -141,7 +141,7 @@ instance Core.AWSRequest GetObjectTorrent where Request.s3vhost Prelude.. Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetObjectTorrentResponse' Prelude.<$> (h Data..#? "x-amz-request-charged") diff --git a/lib/services/amazonka-sagemaker-geospatial/gen/Amazonka/SageMakerGeoSpatial/GetTile.hs b/lib/services/amazonka-sagemaker-geospatial/gen/Amazonka/SageMakerGeoSpatial/GetTile.hs index 9ae3d8e2276..7f8337d53c4 100644 --- a/lib/services/amazonka-sagemaker-geospatial/gen/Amazonka/SageMakerGeoSpatial/GetTile.hs +++ b/lib/services/amazonka-sagemaker-geospatial/gen/Amazonka/SageMakerGeoSpatial/GetTile.hs @@ -197,7 +197,7 @@ instance Core.AWSRequest GetTile where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetTileResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s)) diff --git a/lib/services/amazonka-workmailmessageflow/gen/Amazonka/WorkMailMessageFlow/GetRawMessageContent.hs b/lib/services/amazonka-workmailmessageflow/gen/Amazonka/WorkMailMessageFlow/GetRawMessageContent.hs index 3bc70a6a4e3..a530604fa38 100644 --- a/lib/services/amazonka-workmailmessageflow/gen/Amazonka/WorkMailMessageFlow/GetRawMessageContent.hs +++ b/lib/services/amazonka-workmailmessageflow/gen/Amazonka/WorkMailMessageFlow/GetRawMessageContent.hs @@ -82,7 +82,7 @@ instance Core.AWSRequest GetRawMessageContent where request overrides = Request.get (overrides defaultService) response = - Response.receiveBody + Response.receiveStreamingBody ( \s h x -> GetRawMessageContentResponse' Prelude.<$> (Prelude.pure (Prelude.fromEnum s))