Skip to content

Commit

Permalink
Added getResponseStream
Browse files Browse the repository at this point in the history
  • Loading branch information
relentless committed Oct 29, 2014
1 parent 1e7d686 commit 065334a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
<None Include="app.config" />
<Compile Include="HttpServer.fs" />
<Compile Include="HttpClient_IntegrationTests.fs" />
<None Include="test proxy.fsx" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
Expand Down
24 changes: 24 additions & 0 deletions HttpClient.IntegrationTests/HttpClient_IntegrationTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,30 @@ type ``Integration tests`` ()=
let noBytes = Array.create 0 (new Byte())
response |> should equal noBytes

[<Test>]
member x.``getResponseStream can access the response stream by passing a function`` () =

let asString (sourceStream:Stream) =
use reader = new StreamReader(sourceStream)
reader.ReadToEnd()

let responseFromStream = createRequest Get "http://localhost:1234/TestServer/Raw" |> getResponseStream asString

responseFromStream |> should equal "body"

[<Test>]
member x.``Closing the response stream retrieved from getResponseStream does not cause an exception`` () =

let responseStream = createRequest Get "http://localhost:1234/TestServer/Raw" |> getResponseStream id
responseStream.Close |> ignore

[<Test>]
member x.``Trying to access the response stream after getResponseStream causes an ArgumentException`` () =

(fun() -> new StreamReader(createRequest Get "http://localhost:1234/TestServer/Raw" |> getResponseStream id) |> ignore)
|> should throw typeof<ArgumentException>


// TODO: test proxy - approach below doesn't seem to work, even without port specified in proxy (which appends it to the end of the URL)
// There's a script called 'test proxy' which can be used to test it manually.

Expand Down
28 changes: 23 additions & 5 deletions HttpClient.SampleApplication/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ let complexRequest() =
let downloadImage() =
let response = createRequest Get "http://fsharp.org/img/logo.png" |> getResponseBytes

printfn "Please enter path to save the image, e.g. c:/temp (file will be testImage.png)"
printfn "Please enter path to save the image to, e.g. c:/temp (file will be testImage.png)"
let filename = Console.ReadLine() + "/testImage.png"

use file = File.Create(filename)
Expand All @@ -89,12 +89,27 @@ let downloadImagesInParallel images =
|> ignore
printfn "Images downloaded in parallel in %d ms" timer.ElapsedMilliseconds

// access the response stream and save it to a file directly
let downloadLargeFile() =

printfn "Please enter path to save the 'large' file to, e.g. c:/temp (file will be large.bin)"
let filename = Console.ReadLine() + "/large.bin"

let saveToFile (sourceStream:Stream) =
use destStream = new FileStream(filename, FileMode.Create)
sourceStream.CopyTo(destStream)

createRequest Get "http://fsharp.org/img/logo.png" |> getResponseStream saveToFile

printfn "'%s' downloaded" filename

[<EntryPoint>]
let Main(_) =

printfn "** Word Count **"
countWords()

printfn "\nDownloading sites: Sequential vs Parallel..."
printfn "\n** Downloading sites: Sequential vs Parallel **"

let sites = [
"http://news.bbc.co.uk"
Expand All @@ -105,13 +120,13 @@ let Main(_) =
sites |> downloadSequentially
sites |> downloadInParallel

printfn "\nCreating a complex request.."
printfn "\n** Creating a complex request **"
complexRequest()

printfn "\nDownloading image..."
printfn "\n** Downloading image **"
downloadImage()

printfn "\nDownloading images: Sequential vs Parallel..."
printfn "\n** Downloading images: Sequential vs Parallel **"

let images = [
"http://fsharp.org/img/sup/quantalea.png"
Expand All @@ -122,5 +137,8 @@ let Main(_) =
images |> downloadImagesSequentially
images |> downloadImagesInParallel

printfn "\n** Downloading a 'large' file directly from the response stream **"
downloadLargeFile()

returnToContinue "Press Return to exit"
0
11 changes: 10 additions & 1 deletion HttpClient/HttpClient.fs
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,13 @@ let getResponseAsync request = async {

/// Sends the HTTP request and returns the full response as a Response record.
let getResponse request =
getResponseAsync request |> Async.RunSynchronously
getResponseAsync request |> Async.RunSynchronously

/// Passes the response stream to the passed consumer function.
/// Useful if accessing a large file, as won't copy to memory.
///
/// The response stream will be closed automatically, do not access it outside the function scope.
let getResponseStream streamConsumer request =
use response = request |> toHttpWebRequest |> getResponseNoException |> Async.RunSynchronously
use responseStream = response.GetResponseStream()
streamConsumer (responseStream)

0 comments on commit 065334a

Please sign in to comment.