Allow stream return type (#39)

This commit is contained in:
Patrick Stevens
2023-12-29 18:36:10 +00:00
committed by GitHub
parent dc0f0803b3
commit 9e9744d37b
6 changed files with 155 additions and 1 deletions

View File

@@ -9,6 +9,7 @@ namespace PureGym
open System
open System.Threading
open System.Threading.Tasks
open System.IO
open RestEase
/// Module for constructing a REST client.
@@ -218,4 +219,64 @@ module PureGymApi =
return node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetStream (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (client.BaseAddress, System.Uri ("endpoint", System.UriKind.Relative))
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! node = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
return node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetStream' (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (client.BaseAddress, System.Uri ("endpoint", System.UriKind.Relative))
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! node = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
return node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
member _.GetStream'' (ct : CancellationToken option) =
async {
let! ct = Async.CancellationToken
let uri =
System.Uri (client.BaseAddress, System.Uri ("endpoint", System.UriKind.Relative))
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
let response = response.EnsureSuccessStatusCode ()
let! node = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask
return node
}
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
}

View File

@@ -3,6 +3,7 @@ namespace PureGym
open System
open System.Threading
open System.Threading.Tasks
open System.IO
open RestEase
[<WoofWare.Myriad.Plugins.HttpClient>]
@@ -29,3 +30,12 @@ type IPureGymApi =
[<Get "endpoint/{param}">]
abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>
[<Get "endpoint">]
abstract GetStream : ?ct : CancellationToken -> Task<System.IO.Stream>
[<Get "endpoint">]
abstract GetStream' : ?ct : CancellationToken -> Task<IO.Stream>
[<Get "endpoint">]
abstract GetStream'' : ?ct : CancellationToken -> Task<Stream>

View File

@@ -9,6 +9,7 @@
<ItemGroup>
<Compile Include="HttpClient.fs"/>
<Compile Include="TestPathParam.fs" />
<Compile Include="TestReturnTypes.fs" />
<Compile Include="TestSurface.fs"/>
<Compile Include="TestRemoveOptions.fs"/>
<Compile Include="TestJsonParse.fs"/>

View File

@@ -0,0 +1,58 @@
namespace MyriadPlugin.Test
open System
open System.IO
open System.Net
open FsUnitTyped
open System.Net.Http
open PureGym
open NUnit.Framework
[<TestFixture>]
module TestReturnTypes =
[<Test>]
let ``String return`` () =
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
async {
message.Method |> shouldEqual HttpMethod.Get
let content = new StringContent ("this is not a JSON string")
let resp = new HttpResponseMessage (HttpStatusCode.OK)
resp.Content <- content
return resp
}
use client = HttpClientMock.make (Uri "https://example.com") proc
let api = PureGymApi.make client
api.GetPathParam("hi").Result |> shouldEqual "this is not a JSON string"
[<TestCase "GetStream">]
[<TestCase "GetStream'">]
[<TestCase "GetStream''">]
let ``Stream return`` (case : string) =
let result = [| 1uy ; 2uy ; 3uy ; 4uy |]
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
async {
message.Method |> shouldEqual HttpMethod.Get
let result = new MemoryStream (result)
let content = new StreamContent (result)
let resp = new HttpResponseMessage (HttpStatusCode.OK)
resp.Content <- content
return resp
}
use client = HttpClientMock.make (Uri "https://example.com") proc
let api = PureGymApi.make client
use stream =
match case with
| "GetStream" -> api.GetStream().Result
| "GetStream'" -> api.GetStream'().Result
| "GetStream''" -> api.GetStream''().Result
| _ -> failwith $"unrecognised case: %s{case}"
let buf = Array.zeroCreate 10
stream.Read (buf, 0, 10) |> shouldEqual 4
Array.take 4 buf |> shouldEqual result

View File

@@ -116,6 +116,16 @@ module internal SynTypePatterns =
| _ -> None
| _ -> None
let (|Stream|_|) (fieldType : SynType) : unit option =
match fieldType with
| SynType.LongIdent ident ->
match ident.LongIdent |> List.map (fun i -> i.idText) with
| [ "System" ; "IO" ; "Stream" ]
| [ "IO" ; "Stream" ]
| [ "Stream" ] -> Some ()
| _ -> None
| _ -> None
let (|NumberType|_|) (fieldType : SynType) =
match fieldType with
| SynType.LongIdent ident ->

View File

@@ -331,7 +331,8 @@ module internal HttpClientGenerator =
let returnExpr =
match info.ReturnType with
| String -> SynExpr.CreateIdentString "node"
| String
| Stream -> SynExpr.CreateIdentString "node"
| _ ->
JsonParseGenerator.parseNode
None
@@ -412,6 +413,19 @@ module internal HttpClientGenerator =
)
)
)
| Stream ->
yield
LetBang (
"node",
SynExpr.awaitTask (
SynExpr.CreateApp (
SynExpr.CreateLongIdent (
SynLongIdent.Create [ "response" ; "Content" ; "ReadAsStreamAsync" ]
),
SynExpr.CreateIdentString "ct"
)
)
)
| _ ->
yield
LetBang (