mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-05 20:18:43 +00:00
Implement AllowAnyStatusCode (#41)
This commit is contained in:
@@ -361,4 +361,43 @@ module PureGymApi =
|
||||
return node
|
||||
}
|
||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||
|
||||
member _.GetWithAnyReturnCode (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 node = response
|
||||
return node
|
||||
}
|
||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||
|
||||
member _.GetWithoutAnyReturnCode (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
|
||||
return node
|
||||
}
|
||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||
}
|
||||
|
@@ -16,13 +16,13 @@ type IPureGymApi =
|
||||
[<Get "v1/gyms/{gym_id}/attendance">]
|
||||
abstract GetGymAttendance : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<GymAttendance>
|
||||
|
||||
[<Get "v1/member">]
|
||||
[<RestEase.GetAttribute "v1/member">]
|
||||
abstract GetMember : ?ct : CancellationToken -> Task<Member>
|
||||
|
||||
[<Get "v1/gyms/{gym_id}">]
|
||||
[<RestEase.Get "v1/gyms/{gym_id}">]
|
||||
abstract GetGym : [<Path "gym_id">] gymId : int * ?ct : CancellationToken -> Task<Gym>
|
||||
|
||||
[<Get "v1/member/activity">]
|
||||
[<GetAttribute "v1/member/activity">]
|
||||
abstract GetMemberActivity : ?ct : CancellationToken -> Task<MemberActivityDto>
|
||||
|
||||
// We'll use this one to check handling of absolute URIs too
|
||||
@@ -53,3 +53,10 @@ type IPureGymApi =
|
||||
|
||||
[<Get "endpoint">]
|
||||
abstract GetResponseMessage''' : ?ct : CancellationToken -> Task<HttpResponseMessage>
|
||||
|
||||
[<Get "endpoint">]
|
||||
[<AllowAnyStatusCode>]
|
||||
abstract GetWithAnyReturnCode : ?ct : CancellationToken -> Task<HttpResponseMessage>
|
||||
|
||||
[<Get "endpoint">]
|
||||
abstract GetWithoutAnyReturnCode : ?ct : CancellationToken -> Task<HttpResponseMessage>
|
||||
|
@@ -10,6 +10,7 @@
|
||||
<Compile Include="HttpClient.fs"/>
|
||||
<Compile Include="TestPathParam.fs" />
|
||||
<Compile Include="TestReturnTypes.fs" />
|
||||
<Compile Include="TestAllowAnyStatusCode.fs" />
|
||||
<Compile Include="TestSurface.fs"/>
|
||||
<Compile Include="TestRemoveOptions.fs"/>
|
||||
<Compile Include="TestJsonParse.fs"/>
|
||||
|
62
MyriadPlugin.Test/TestAllowAnyStatusCode.fs
Normal file
62
MyriadPlugin.Test/TestAllowAnyStatusCode.fs
Normal file
@@ -0,0 +1,62 @@
|
||||
namespace MyriadPlugin.Test
|
||||
|
||||
open System
|
||||
open System.Net
|
||||
open System.Net.Http
|
||||
open NUnit.Framework
|
||||
open FsUnitTyped
|
||||
open PureGym
|
||||
|
||||
[<TestFixture>]
|
||||
module TestAllowAnyStatusCode =
|
||||
|
||||
[<Test>]
|
||||
let ``Without AllowAnyStatusCode we throw`` () =
|
||||
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||
async {
|
||||
message.Method |> shouldEqual HttpMethod.Get
|
||||
let content = new StringContent ("nothing was here :(")
|
||||
let resp = new HttpResponseMessage (HttpStatusCode.NotFound)
|
||||
resp.Content <- content
|
||||
return resp
|
||||
}
|
||||
|
||||
use client = HttpClientMock.make (Uri "https://example.com") proc
|
||||
let api = PureGymApi.make client
|
||||
|
||||
let exc =
|
||||
async {
|
||||
let! message = Async.AwaitTask (api.GetWithoutAnyReturnCode ()) |> Async.Catch
|
||||
|
||||
match message with
|
||||
| Choice1Of2 _ -> return failwith "test failure"
|
||||
| Choice2Of2 exc -> return exc
|
||||
}
|
||||
|> Async.RunSynchronously
|
||||
|
||||
let exc =
|
||||
match exc with
|
||||
| :? AggregateException as exc -> exc
|
||||
| exc -> failwith $"Test failure: expected AggregateException, got %+A{exc}"
|
||||
|
||||
match exc.InnerException with
|
||||
| :? HttpRequestException as exc -> exc.Message.Contains "404 (Not Found)" |> shouldEqual true
|
||||
| e -> failwith $"Test failure: %+A{e}"
|
||||
|
||||
[<Test>]
|
||||
let ``With AllowAnyStatusCode we do not throw`` () =
|
||||
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||
async {
|
||||
message.Method |> shouldEqual HttpMethod.Get
|
||||
let content = new StringContent ("nothing was here :(")
|
||||
let resp = new HttpResponseMessage (HttpStatusCode.NotFound)
|
||||
resp.Content <- content
|
||||
return resp
|
||||
}
|
||||
|
||||
use client = HttpClientMock.make (Uri "https://example.com") proc
|
||||
let api = PureGymApi.make client
|
||||
|
||||
let message = api.GetWithAnyReturnCode().Result
|
||||
message.StatusCode |> shouldEqual HttpStatusCode.NotFound
|
||||
message.Content.ReadAsStringAsync().Result |> shouldEqual "nothing was here :("
|
@@ -52,6 +52,7 @@ module internal HttpClientGenerator =
|
||||
Arity : SynArgInfo list
|
||||
Args : Parameter list
|
||||
Identifier : Ident
|
||||
EnsureSuccessHttpCode : bool
|
||||
}
|
||||
|
||||
let httpMethodString (m : HttpMethod) : string =
|
||||
@@ -116,6 +117,17 @@ module internal HttpClientGenerator =
|
||||
| matchingAttrs ->
|
||||
failwithf "Required exactly one recognised RestEase attribute on member, but got %i" matchingAttrs.Length
|
||||
|
||||
let shouldAllowAnyStatusCode (attrs : SynAttribute list) : bool =
|
||||
attrs
|
||||
|> List.exists (fun attr ->
|
||||
match attr.TypeName.AsString with
|
||||
| "AllowAnyStatusCode"
|
||||
| "AllowAnyStatusCodeAttribute"
|
||||
| "RestEase.AllowAnyStatusCode"
|
||||
| "RestEase.AllowAnyStatusCodeAttribute" -> true
|
||||
| _ -> false
|
||||
)
|
||||
|
||||
let constructMember (info : MemberInfo) : SynMemberDefn =
|
||||
let valInfo =
|
||||
SynValInfo.SynValInfo (
|
||||
@@ -392,14 +404,15 @@ module internal HttpClientGenerator =
|
||||
)
|
||||
)
|
||||
)
|
||||
yield
|
||||
Let (
|
||||
"response",
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "response" ; "EnsureSuccessStatusCode" ]),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
if info.EnsureSuccessHttpCode then
|
||||
yield
|
||||
Let (
|
||||
"response",
|
||||
SynExpr.CreateApp (
|
||||
SynExpr.CreateLongIdent (SynLongIdent.Create [ "response" ; "EnsureSuccessStatusCode" ]),
|
||||
SynExpr.CreateConst SynConst.Unit
|
||||
)
|
||||
)
|
||||
)
|
||||
match info.ReturnType with
|
||||
| HttpResponseMessage -> yield Let ("node", SynExpr.CreateIdentString "response")
|
||||
| String ->
|
||||
@@ -617,6 +630,8 @@ module internal HttpClientGenerator =
|
||||
|
||||
let httpMethod, url = extractHttpInformation attrs
|
||||
|
||||
let shouldEnsureSuccess = not (shouldAllowAnyStatusCode attrs)
|
||||
|
||||
{
|
||||
HttpMethod = httpMethod
|
||||
UrlTemplate = url
|
||||
@@ -624,6 +639,7 @@ module internal HttpClientGenerator =
|
||||
Arity = arity
|
||||
Args = args
|
||||
Identifier = ident
|
||||
EnsureSuccessHttpCode = shouldEnsureSuccess
|
||||
}
|
||||
| _ -> failwithf "Unrecognised member definition: %+A" defn
|
||||
)
|
||||
|
Reference in New Issue
Block a user