From ad2eeaaa4f07db9ee2bf4cc12edd96c16bcc3367 Mon Sep 17 00:00:00 2001 From: Patrick Stevens <3138005+Smaug123@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:47:59 +0000 Subject: [PATCH] URI support (#59) --- ConsumePlugin/GeneratedPureGymDto.fs | 24 +++++++++++++++ ConsumePlugin/GeneratedRestClient.fs | 30 +++++++++++++++++++ ConsumePlugin/PureGymDto.fs | 6 ++++ ConsumePlugin/RestApiExample.fs | 3 ++ .../TestHttpClient/TestPureGymRestApi.fs | 24 +++++++++++++++ WoofWare.Myriad.Plugins/AstHelper.fs | 9 ++++++ WoofWare.Myriad.Plugins/JsonParseGenerator.fs | 4 +++ 7 files changed, 100 insertions(+) diff --git a/ConsumePlugin/GeneratedPureGymDto.fs b/ConsumePlugin/GeneratedPureGymDto.fs index 7fc1049..d0ce354 100644 --- a/ConsumePlugin/GeneratedPureGymDto.fs +++ b/ConsumePlugin/GeneratedPureGymDto.fs @@ -944,3 +944,27 @@ module Sessions = Summary = Summary Visits = Visits } +namespace PureGym + +/// Module containing JSON parsing methods for the UriThing type +[] +[] +module UriThing = + /// Parse from a JSON node. + let jsonParse (node : System.Text.Json.Nodes.JsonNode) : UriThing = + let SomeUri = + (match node.["someUri"] with + | null -> + raise ( + System.Collections.Generic.KeyNotFoundException ( + sprintf "Required key '%s' not found on JSON object" ("someUri") + ) + ) + | v -> v) + .AsValue() + .GetValue () + |> System.Uri + + { + SomeUri = SomeUri + } diff --git a/ConsumePlugin/GeneratedRestClient.fs b/ConsumePlugin/GeneratedRestClient.fs index 9b0da01..39efb85 100644 --- a/ConsumePlugin/GeneratedRestClient.fs +++ b/ConsumePlugin/GeneratedRestClient.fs @@ -180,6 +180,36 @@ module PureGymApi = } |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) + member _.GetUrl (ct : CancellationToken option) = + async { + let! ct = Async.CancellationToken + + let uri = + System.Uri ( + (match client.BaseAddress with + | null -> System.Uri "https://whatnot.com" + | v -> v), + System.Uri ("some/url", 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! stream = response.Content.ReadAsStreamAsync ct |> Async.AwaitTask + + let! node = + System.Text.Json.Nodes.JsonNode.ParseAsync (stream, cancellationToken = ct) + |> Async.AwaitTask + + return UriThing.jsonParse node + } + |> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct)) + member _.GetSessions (fromDate : DateOnly, toDate : DateOnly, ct : CancellationToken option) = async { let! ct = Async.CancellationToken diff --git a/ConsumePlugin/PureGymDto.fs b/ConsumePlugin/PureGymDto.fs index 455ed88..1010dd8 100644 --- a/ConsumePlugin/PureGymDto.fs +++ b/ConsumePlugin/PureGymDto.fs @@ -177,3 +177,9 @@ type Sessions = [] Visits : Visit list } + +[] +type UriThing = + { + SomeUri : Uri + } diff --git a/ConsumePlugin/RestApiExample.fs b/ConsumePlugin/RestApiExample.fs index 7e97703..b1bafb6 100644 --- a/ConsumePlugin/RestApiExample.fs +++ b/ConsumePlugin/RestApiExample.fs @@ -26,6 +26,9 @@ type IPureGymApi = [] abstract GetMemberActivity : ?ct : CancellationToken -> Task + [] + abstract GetUrl : ?ct : CancellationToken -> Task + // We'll use this one to check handling of absolute URIs too [] abstract GetSessions : diff --git a/WoofWare.Myriad.Plugins.Test/TestHttpClient/TestPureGymRestApi.fs b/WoofWare.Myriad.Plugins.Test/TestHttpClient/TestPureGymRestApi.fs index 446f4ba..acc4960 100644 --- a/WoofWare.Myriad.Plugins.Test/TestHttpClient/TestPureGymRestApi.fs +++ b/WoofWare.Myriad.Plugins.Test/TestHttpClient/TestPureGymRestApi.fs @@ -236,3 +236,27 @@ module TestPureGymRestApi = let api = PureGymApi.make client api.GetSessions(startDate, endDate).Result |> shouldEqual expected + + [] + let ``URI example`` () = + let proc (message : HttpRequestMessage) : HttpResponseMessage Async = + async { + message.Method |> shouldEqual HttpMethod.Get + + message.RequestUri.ToString () |> shouldEqual "https://whatnot.com/some/url" + + let content = + new StringContent ("""{"someUri": "https://patrick@en.wikipedia.org/wiki/foo"}""") + + let resp = new HttpResponseMessage (HttpStatusCode.OK) + resp.Content <- content + return resp + } + + use client = HttpClientMock.makeNoUri proc + let api = PureGymApi.make client + + let uri = api.GetUrl().Result.SomeUri + uri.ToString () |> shouldEqual "https://patrick@en.wikipedia.org/wiki/foo" + uri.UserInfo |> shouldEqual "patrick" + uri.Host |> shouldEqual "en.wikipedia.org" diff --git a/WoofWare.Myriad.Plugins/AstHelper.fs b/WoofWare.Myriad.Plugins/AstHelper.fs index 4d04b46..c005985 100644 --- a/WoofWare.Myriad.Plugins/AstHelper.fs +++ b/WoofWare.Myriad.Plugins/AstHelper.fs @@ -423,6 +423,15 @@ module internal SynTypePatterns = | _ -> None | _ -> None + let (|Uri|_|) (fieldType : SynType) = + match fieldType with + | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> + match ident |> List.map (fun i -> i.idText) with + | [ "System" ; "Uri" ] + | [ "Uri" ] -> Some () + | _ -> None + | _ -> None + let (|Task|_|) (fieldType : SynType) : SynType option = match fieldType with | SynType.App (SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)), _, args, _, _, _, _) -> diff --git a/WoofWare.Myriad.Plugins/JsonParseGenerator.fs b/WoofWare.Myriad.Plugins/JsonParseGenerator.fs index c55d4b8..5121add 100644 --- a/WoofWare.Myriad.Plugins/JsonParseGenerator.fs +++ b/WoofWare.Myriad.Plugins/JsonParseGenerator.fs @@ -136,6 +136,10 @@ module internal JsonParseGenerator = |> SynExpr.pipeThroughFunction ( SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "DateOnly" ; "Parse" ]) ) + | Uri -> + node + |> asValueGetValue propertyName "string" + |> SynExpr.pipeThroughFunction (SynExpr.CreateLongIdent (SynLongIdent.Create [ "System" ; "Uri" ])) | DateTime -> node |> asValueGetValue propertyName "string"