brendanhay / amazonka

A comprehensive Amazon Web Services SDK for Haskell.
https://amazonka.brendanhay.nz
Other
599 stars 227 forks source link

Reading streaming response fails with `ConnectionClosed` #463

Closed zyla closed 6 years ago

zyla commented 6 years ago

In this change: https://github.com/brendanhay/amazonka/commit/99eb0cb1a5552c9f63ef8aa31109ce3a115c1c09#diff-e434647b935b7bea05381ac026de8177R124, catches go handlers was replaced by liftIO $ catches (runResourceT go) handlers. But these two expressions have very different semantics.

runResourceT finalizes all resources acquired by go, including HTTP connections. This change broke streaming response handling, because the connection is prematurely closed by perform.

Here's a test program that demonstrates the issue (requires access to AWS Polly):

{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Control.Lens
import qualified Control.Lens           as L
import           Control.Monad.IO.Class
import           Data.Conduit.Binary
import qualified Network.AWS            as AWS
import qualified Network.AWS.Polly      as Polly
import           System.IO

main :: IO ()
main = do
  awsEnv <- AWS.newEnv AWS.Discover

  logger <- AWS.newLogger AWS.Trace stdout
  let env' = awsEnv & AWS.envLogger .~ logger

  let text = "Hello World"

  AWS.runResourceT $ AWS.runAWS env' $ do
    response <- AWS.send $
      L.set Polly.ssLexiconNames [ "restaurants" ] $
      Polly.synthesizeSpeech Polly.MP3 text Polly.Maja

    liftIO $ putStrLn "Response is OK, receiving data"
    (response ^. Polly.ssrsAudioStream) `AWS.sinkBody` sinkFile "test.mp3"

Works fine with amazonka 1.5.0. On 1.6.0 and develop, fails with the following output:

[Client Request] { ... omitted ... }
[Client Response] { ... omitted ... }
Response is OK, receiving data
*** Exception: HttpExceptionRequest Request {
  host                 = "polly.us-east-1.amazonaws.com"
  port                 = 443
  secure               = True
  requestHeaders       = ... omitted ...
  path                 = "/v1/speech"
  queryString          = ""
  method               = "POST"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 0
  responseTimeout      = ResponseTimeoutMicro 70000000
  requestVersion       = HTTP/1.1
}
 ConnectionClosed
brendanhay commented 6 years ago

Thanks for the detailed analysis @zyla - and apologies for letting this slip through in the recent release.