mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-05 20:18:43 +00:00
Add JSON headers automatically to Body in HTTP client (#395)
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
Notable changes are recorded here.
|
Notable changes are recorded here.
|
||||||
|
|
||||||
|
# WoofWare.Myriad.Plugins 8.0.3
|
||||||
|
|
||||||
|
The RestEase-style HTTP client generator now automatically adds the `application/json` content type header to requests which are POSTing a body that is known to be JSON-serialised.
|
||||||
|
You can override this by setting the `[<RestEase.Header ("Content-Type", "desired content type")>]` header manually on any affected member.
|
||||||
|
|
||||||
# WoofWare.Myriad.Plugins 7.0.1
|
# WoofWare.Myriad.Plugins 7.0.1
|
||||||
|
|
||||||
All generators should now be compatible with `<Nullable>enable</Nullable>`.
|
All generators should now be compatible with `<Nullable>enable</Nullable>`.
|
||||||
|
@@ -375,7 +375,9 @@ module PureGymApi =
|
|||||||
match node with
|
match node with
|
||||||
| None -> "null"
|
| None -> "null"
|
||||||
| Some node -> node.ToJsonString ()
|
| Some node -> node.ToJsonString ()
|
||||||
)
|
),
|
||||||
|
null,
|
||||||
|
"application/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
do httpMessage.Content <- queryParams
|
do httpMessage.Content <- queryParams
|
||||||
@@ -667,7 +669,9 @@ module PureGymApi =
|
|||||||
|
|
||||||
let queryParams =
|
let queryParams =
|
||||||
new System.Net.Http.StringContent (
|
new System.Net.Http.StringContent (
|
||||||
user |> PureGym.Member.toJsonNode |> (fun node -> node.ToJsonString ())
|
user |> PureGym.Member.toJsonNode |> (fun node -> node.ToJsonString ()),
|
||||||
|
null,
|
||||||
|
"application/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
do httpMessage.Content <- queryParams
|
do httpMessage.Content <- queryParams
|
||||||
@@ -710,7 +714,9 @@ module PureGymApi =
|
|||||||
)
|
)
|
||||||
| field -> field)
|
| field -> field)
|
||||||
)
|
)
|
||||||
|> (fun node -> node.ToJsonString ())
|
|> (fun node -> node.ToJsonString ()),
|
||||||
|
null,
|
||||||
|
"application/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
do httpMessage.Content <- queryParams
|
do httpMessage.Content <- queryParams
|
||||||
@@ -753,7 +759,9 @@ module PureGymApi =
|
|||||||
)
|
)
|
||||||
| field -> field)
|
| field -> field)
|
||||||
)
|
)
|
||||||
|> (fun node -> node.ToJsonString ())
|
|> (fun node -> node.ToJsonString ()),
|
||||||
|
null,
|
||||||
|
"application/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
do httpMessage.Content <- queryParams
|
do httpMessage.Content <- queryParams
|
||||||
@@ -1801,3 +1809,174 @@ module ApiWithHeaders2 =
|
|||||||
}
|
}
|
||||||
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
}
|
}
|
||||||
|
namespace PureGym
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open System.IO
|
||||||
|
open System.Net
|
||||||
|
open System.Net.Http
|
||||||
|
open RestEase
|
||||||
|
|
||||||
|
/// Module for constructing a REST client.
|
||||||
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
|
module ClientWithJsonBody =
|
||||||
|
/// Create a REST client.
|
||||||
|
let make (client : System.Net.Http.HttpClient) : IClientWithJsonBody =
|
||||||
|
{ new IClientWithJsonBody with
|
||||||
|
member _.GetPathParam (parameter : string, mem : PureGym.Member, ct : CancellationToken option) =
|
||||||
|
async {
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
(match client.BaseAddress with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.ArgumentNullException (
|
||||||
|
nameof (client.BaseAddress),
|
||||||
|
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v),
|
||||||
|
System.Uri (
|
||||||
|
"endpoint/{param}"
|
||||||
|
.Replace ("{param}", parameter.ToString () |> System.Uri.EscapeDataString),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let httpMessage =
|
||||||
|
new System.Net.Http.HttpRequestMessage (
|
||||||
|
Method = System.Net.Http.HttpMethod.Post,
|
||||||
|
RequestUri = uri
|
||||||
|
)
|
||||||
|
|
||||||
|
let queryParams =
|
||||||
|
new System.Net.Http.StringContent (
|
||||||
|
mem |> PureGym.Member.toJsonNode |> (fun node -> node.ToJsonString ()),
|
||||||
|
null,
|
||||||
|
"application/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
do httpMessage.Content <- queryParams
|
||||||
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
|
let response = response.EnsureSuccessStatusCode ()
|
||||||
|
let! responseString = response.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
return responseString
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
}
|
||||||
|
namespace PureGym
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open System.IO
|
||||||
|
open System.Net
|
||||||
|
open System.Net.Http
|
||||||
|
open RestEase
|
||||||
|
|
||||||
|
/// Module for constructing a REST client.
|
||||||
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
|
module ClientWithJsonBodyOverridden =
|
||||||
|
/// Create a REST client.
|
||||||
|
let make (client : System.Net.Http.HttpClient) : IClientWithJsonBodyOverridden =
|
||||||
|
{ new IClientWithJsonBodyOverridden with
|
||||||
|
member _.GetPathParam (parameter : string, mem : PureGym.Member, ct : CancellationToken option) =
|
||||||
|
async {
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
(match client.BaseAddress with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.ArgumentNullException (
|
||||||
|
nameof (client.BaseAddress),
|
||||||
|
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v),
|
||||||
|
System.Uri (
|
||||||
|
"endpoint/{param}"
|
||||||
|
.Replace ("{param}", parameter.ToString () |> System.Uri.EscapeDataString),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let httpMessage =
|
||||||
|
new System.Net.Http.HttpRequestMessage (
|
||||||
|
Method = System.Net.Http.HttpMethod.Post,
|
||||||
|
RequestUri = uri
|
||||||
|
)
|
||||||
|
|
||||||
|
let queryParams =
|
||||||
|
new System.Net.Http.StringContent (
|
||||||
|
mem |> PureGym.Member.toJsonNode |> (fun node -> node.ToJsonString ()),
|
||||||
|
null,
|
||||||
|
"application/ecmascript"
|
||||||
|
)
|
||||||
|
|
||||||
|
do httpMessage.Content <- queryParams
|
||||||
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
|
let response = response.EnsureSuccessStatusCode ()
|
||||||
|
let! responseString = response.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
return responseString
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
}
|
||||||
|
namespace PureGym
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open System.IO
|
||||||
|
open System.Net
|
||||||
|
open System.Net.Http
|
||||||
|
open RestEase
|
||||||
|
|
||||||
|
/// Module for constructing a REST client.
|
||||||
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix) ; RequireQualifiedAccess>]
|
||||||
|
module ClientWithStringBody =
|
||||||
|
/// Create a REST client.
|
||||||
|
let make (client : System.Net.Http.HttpClient) : IClientWithStringBody =
|
||||||
|
{ new IClientWithStringBody with
|
||||||
|
member _.GetPathParam (parameter : string, mem : string, ct : CancellationToken option) =
|
||||||
|
async {
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
|
||||||
|
let uri =
|
||||||
|
System.Uri (
|
||||||
|
(match client.BaseAddress with
|
||||||
|
| null ->
|
||||||
|
raise (
|
||||||
|
System.ArgumentNullException (
|
||||||
|
nameof (client.BaseAddress),
|
||||||
|
"No base address was supplied on the type, and no BaseAddress was on the HttpClient."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
| v -> v),
|
||||||
|
System.Uri (
|
||||||
|
"endpoint/{param}"
|
||||||
|
.Replace ("{param}", parameter.ToString () |> System.Uri.EscapeDataString),
|
||||||
|
System.UriKind.Relative
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
let httpMessage =
|
||||||
|
new System.Net.Http.HttpRequestMessage (
|
||||||
|
Method = System.Net.Http.HttpMethod.Post,
|
||||||
|
RequestUri = uri
|
||||||
|
)
|
||||||
|
|
||||||
|
let queryParams = new System.Net.Http.StringContent (mem)
|
||||||
|
do httpMessage.Content <- queryParams
|
||||||
|
let! response = client.SendAsync (httpMessage, ct) |> Async.AwaitTask
|
||||||
|
let response = response.EnsureSuccessStatusCode ()
|
||||||
|
let! responseString = response.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
return responseString
|
||||||
|
}
|
||||||
|
|> (fun a -> Async.StartAsTask (a, ?cancellationToken = ct))
|
||||||
|
}
|
||||||
|
@@ -203,3 +203,35 @@ type IApiWithHeaders2 =
|
|||||||
[<Get "endpoint/{param}">]
|
[<Get "endpoint/{param}">]
|
||||||
abstract GetPathParam :
|
abstract GetPathParam :
|
||||||
[<WoofWare.Myriad.Plugins.RestEase.Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>
|
[<WoofWare.Myriad.Plugins.RestEase.Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.HttpClient>]
|
||||||
|
type IClientWithJsonBody =
|
||||||
|
// As a POST request of a JSON-serialised body, we automatically set Content-Type: application/json.
|
||||||
|
[<Post "endpoint/{param}">]
|
||||||
|
abstract GetPathParam :
|
||||||
|
[<RestEase.Path "param">] parameter : string *
|
||||||
|
[<WoofWare.Myriad.Plugins.RestEase.Body>] mem : PureGym.Member *
|
||||||
|
?ct : CancellationToken ->
|
||||||
|
Task<string>
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.HttpClient>]
|
||||||
|
type IClientWithJsonBodyOverridden =
|
||||||
|
// As a POST request of a JSON-serialised body, we *would* automatically set Content-Type: application/json,
|
||||||
|
// but this method has overridden it.
|
||||||
|
[<Post "endpoint/{param}">]
|
||||||
|
[<Header("Content-Type", "application/ecmascript")>]
|
||||||
|
abstract GetPathParam :
|
||||||
|
[<RestEase.Path "param">] parameter : string *
|
||||||
|
[<WoofWare.Myriad.Plugins.RestEase.Body>] mem : PureGym.Member *
|
||||||
|
?ct : CancellationToken ->
|
||||||
|
Task<string>
|
||||||
|
|
||||||
|
[<WoofWare.Myriad.Plugins.HttpClient>]
|
||||||
|
type IClientWithStringBody =
|
||||||
|
// As a POST request of a bare string body, we don't override the Content-Type.
|
||||||
|
[<Post "endpoint/{param}">]
|
||||||
|
abstract GetPathParam :
|
||||||
|
[<RestEase.Path "param">] parameter : string *
|
||||||
|
[<WoofWare.Myriad.Plugins.RestEase.Body>] mem : string *
|
||||||
|
?ct : CancellationToken ->
|
||||||
|
Task<string>
|
||||||
|
@@ -3,10 +3,12 @@ namespace WoofWare.Myriad.Plugins.Test
|
|||||||
open System
|
open System
|
||||||
open System.Net
|
open System.Net
|
||||||
open System.Net.Http
|
open System.Net.Http
|
||||||
|
open System.Text.Json.Nodes
|
||||||
open System.Threading
|
open System.Threading
|
||||||
open NUnit.Framework
|
open NUnit.Framework
|
||||||
open FsUnitTyped
|
open FsUnitTyped
|
||||||
open PureGym
|
open PureGym
|
||||||
|
open WoofWare.Expect
|
||||||
|
|
||||||
[<TestFixture>]
|
[<TestFixture>]
|
||||||
module TestVariableHeader =
|
module TestVariableHeader =
|
||||||
@@ -50,15 +52,17 @@ module TestVariableHeader =
|
|||||||
someHeaderCount.Value |> shouldEqual 10
|
someHeaderCount.Value |> shouldEqual 10
|
||||||
someOtherHeaderCount.Value |> shouldEqual -100
|
someOtherHeaderCount.Value |> shouldEqual -100
|
||||||
|
|
||||||
api.GetPathParam("param").Result.Split "\n"
|
expect {
|
||||||
|> Array.sort
|
snapshotJson
|
||||||
|> shouldEqual
|
@"[
|
||||||
[|
|
""Authorization: -99"",
|
||||||
"Authorization: -99"
|
""Header-Name: Header-Value"",
|
||||||
"Header-Name: Header-Value"
|
""Something-Else: val"",
|
||||||
"Something-Else: val"
|
""X-Foo: 11""
|
||||||
"X-Foo: 11"
|
]"
|
||||||
|]
|
|
||||||
|
return api.GetPathParam("param").Result.Split "\n" |> Array.sort
|
||||||
|
}
|
||||||
|
|
||||||
someHeaderCount.Value |> shouldEqual 11
|
someHeaderCount.Value |> shouldEqual 11
|
||||||
someOtherHeaderCount.Value |> shouldEqual -99
|
someOtherHeaderCount.Value |> shouldEqual -99
|
||||||
@@ -102,25 +106,156 @@ module TestVariableHeader =
|
|||||||
someHeaderCount.Value |> shouldEqual 10
|
someHeaderCount.Value |> shouldEqual 10
|
||||||
someOtherHeaderCount.Value |> shouldEqual -100
|
someOtherHeaderCount.Value |> shouldEqual -100
|
||||||
|
|
||||||
api.GetPathParam("param").Result.Split "\n"
|
expect {
|
||||||
|> Array.sort
|
snapshotJson
|
||||||
|> shouldEqual
|
@"[
|
||||||
[|
|
""Authorization: -99"",
|
||||||
"Authorization: -99"
|
""Header-Name: Header-Value"",
|
||||||
"Header-Name: Header-Value"
|
""Something-Else: val"",
|
||||||
"Something-Else: val"
|
""X-Foo: 11""
|
||||||
"X-Foo: 11"
|
]"
|
||||||
|]
|
|
||||||
|
|
||||||
api.GetPathParam("param").Result.Split "\n"
|
return api.GetPathParam("param").Result.Split "\n" |> Array.sort
|
||||||
|> Array.sort
|
}
|
||||||
|> shouldEqual
|
|
||||||
[|
|
expect {
|
||||||
"Authorization: -98"
|
snapshotJson
|
||||||
"Header-Name: Header-Value"
|
@"[
|
||||||
"Something-Else: val"
|
""Authorization: -98"",
|
||||||
"X-Foo: 12"
|
""Header-Name: Header-Value"",
|
||||||
|]
|
""Something-Else: val"",
|
||||||
|
""X-Foo: 12""
|
||||||
|
]"
|
||||||
|
|
||||||
|
return api.GetPathParam("param").Result.Split "\n" |> Array.sort
|
||||||
|
}
|
||||||
|
|
||||||
someHeaderCount.Value |> shouldEqual 12
|
someHeaderCount.Value |> shouldEqual 12
|
||||||
someOtherHeaderCount.Value |> shouldEqual -98
|
someOtherHeaderCount.Value |> shouldEqual -98
|
||||||
|
|
||||||
|
let pureGymMember =
|
||||||
|
{
|
||||||
|
Id = 3
|
||||||
|
CompoundMemberId = "compound"
|
||||||
|
FirstName = "Patrick"
|
||||||
|
LastName = "Stevens"
|
||||||
|
HomeGymId = 1223
|
||||||
|
HomeGymName = "Arnie's Temple o' Gainz"
|
||||||
|
EmailAddress = "patrick@home"
|
||||||
|
GymAccessPin = "1234"
|
||||||
|
DateOfBirth = DateOnly (1992, 03, 04)
|
||||||
|
MobileNumber = "number"
|
||||||
|
Postcode = "postcode"
|
||||||
|
MembershipName = "member"
|
||||||
|
MembershipLevel = 9999
|
||||||
|
SuspendedReason = -1
|
||||||
|
MemberStatus = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Content-Type header is automatically inserted`` () =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Post
|
||||||
|
|
||||||
|
message.RequestUri.ToString ()
|
||||||
|
|> shouldEqual "https://example.com/endpoint/param"
|
||||||
|
|
||||||
|
let headers =
|
||||||
|
[
|
||||||
|
for h in message.Content.Headers do
|
||||||
|
yield $"%s{h.Key}: %s{Seq.exactlyOne h.Value}"
|
||||||
|
]
|
||||||
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
let! content = message.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
content |> JsonNode.Parse |> Member.jsonParse |> shouldEqual pureGymMember
|
||||||
|
|
||||||
|
let content = new StringContent (headers)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make (Uri "https://example.com") proc
|
||||||
|
|
||||||
|
let api = ClientWithJsonBody.make client
|
||||||
|
let result = api.GetPathParam ("param", pureGymMember) |> _.Result
|
||||||
|
|
||||||
|
expect {
|
||||||
|
snapshot @"Content-Type: application/json; charset=utf-8"
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Content-Type header is respected if overridden`` () =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Post
|
||||||
|
|
||||||
|
message.RequestUri.ToString ()
|
||||||
|
|> shouldEqual "https://example.com/endpoint/param"
|
||||||
|
|
||||||
|
let headers =
|
||||||
|
[
|
||||||
|
for h in message.Content.Headers do
|
||||||
|
yield $"%s{h.Key}: %s{Seq.exactlyOne h.Value}"
|
||||||
|
]
|
||||||
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
let! content = message.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
content |> JsonNode.Parse |> Member.jsonParse |> shouldEqual pureGymMember
|
||||||
|
|
||||||
|
let content = new StringContent (headers)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make (Uri "https://example.com") proc
|
||||||
|
|
||||||
|
let api = ClientWithJsonBodyOverridden.make client
|
||||||
|
let result = api.GetPathParam ("param", pureGymMember) |> _.Result
|
||||||
|
|
||||||
|
expect {
|
||||||
|
snapshot @"Content-Type: application/ecmascript; charset=utf-8"
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``Content-Type header is the default for strings`` () =
|
||||||
|
let proc (message : HttpRequestMessage) : HttpResponseMessage Async =
|
||||||
|
async {
|
||||||
|
message.Method |> shouldEqual HttpMethod.Post
|
||||||
|
|
||||||
|
message.RequestUri.ToString ()
|
||||||
|
|> shouldEqual "https://example.com/endpoint/param"
|
||||||
|
|
||||||
|
let headers =
|
||||||
|
[
|
||||||
|
for h in message.Content.Headers do
|
||||||
|
yield $"%s{h.Key}: %s{Seq.exactlyOne h.Value}"
|
||||||
|
]
|
||||||
|
|> String.concat "\n"
|
||||||
|
|
||||||
|
let! ct = Async.CancellationToken
|
||||||
|
let! content = message.Content.ReadAsStringAsync ct |> Async.AwaitTask
|
||||||
|
content |> shouldEqual "hello!"
|
||||||
|
|
||||||
|
let content = new StringContent (headers)
|
||||||
|
let resp = new HttpResponseMessage (HttpStatusCode.OK)
|
||||||
|
resp.Content <- content
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
use client = HttpClientMock.make (Uri "https://example.com") proc
|
||||||
|
|
||||||
|
let api = ClientWithStringBody.make client
|
||||||
|
let result = api.GetPathParam ("param", "hello!") |> _.Result
|
||||||
|
|
||||||
|
expect {
|
||||||
|
snapshot @"Content-Type: text/plain; charset=utf-8"
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
|
||||||
<PackageReference Include="NUnit" Version="4.3.2"/>
|
<PackageReference Include="NUnit" Version="4.3.2"/>
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
|
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0"/>
|
||||||
|
<PackageReference Include="WoofWare.Expect" Version="0.4.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -453,15 +453,20 @@ module internal HttpClientGenerator =
|
|||||||
|
|
||||||
let contentTypeHeader, memberHeaders =
|
let contentTypeHeader, memberHeaders =
|
||||||
info.Headers
|
info.Headers
|
||||||
|> List.partition (fun (headerName, headerValue) ->
|
|> List.partition (fun (headerName, _headerValue) ->
|
||||||
match headerName |> SynExpr.stripOptionalParen with
|
match headerName |> SynExpr.stripOptionalParen with
|
||||||
| SynExpr.Const (SynConst.String ("Content-Type", _, _), _) -> true
|
| SynExpr.Const (SynConst.String (s, _, _), _) ->
|
||||||
|
System.String.Equals (s, "Content-Type", System.StringComparison.OrdinalIgnoreCase)
|
||||||
| _ -> false
|
| _ -> false
|
||||||
)
|
)
|
||||||
|
|
||||||
let contentTypeHeader =
|
let contentTypeHeader =
|
||||||
match contentTypeHeader with
|
match contentTypeHeader with
|
||||||
| [] -> None
|
| [] ->
|
||||||
|
// Set application/json if we *know* we're sending JSON
|
||||||
|
match bodyParam with
|
||||||
|
| Some (BodyParamMethods.Serialise _, _) -> Some (SynExpr.CreateConst "application/json")
|
||||||
|
| _ -> None
|
||||||
| [ _, ct ] -> Some (SynExpr.stripOptionalParen ct)
|
| [ _, ct ] -> Some (SynExpr.stripOptionalParen ct)
|
||||||
| _ -> failwith "Unexpectedly got multiple Content-Type headers"
|
| _ -> failwith "Unexpectedly got multiple Content-Type headers"
|
||||||
|
|
||||||
|
@@ -44,6 +44,11 @@
|
|||||||
"version": "9.0.202",
|
"version": "9.0.202",
|
||||||
"hash": "sha256-64Gub0qemmCoMa1tDus6TeTuB1+5sHfE6KD2j4o84mA="
|
"hash": "sha256-64Gub0qemmCoMa1tDus6TeTuB1+5sHfE6KD2j4o84mA="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pname": "FSharp.SystemTextJson",
|
||||||
|
"version": "1.4.36",
|
||||||
|
"hash": "sha256-zZEhjP0mdc5E3fBPS4/lqD7sxoaoT5SOspP546RWYdc="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pname": "FsUnit",
|
"pname": "FsUnit",
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
@@ -364,16 +369,31 @@
|
|||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"hash": "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY="
|
"hash": "sha256-BkUYNguz0e4NJp1kkW7aJBn3dyH9STwB5N8XqnlCsmY="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Text.Json",
|
||||||
|
"version": "6.0.10",
|
||||||
|
"hash": "sha256-UijYh0dxFjFinMPSTJob96oaRkNm+Wsa+7Ffg6mRnsc="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pname": "System.Text.Json",
|
"pname": "System.Text.Json",
|
||||||
"version": "8.0.5",
|
"version": "8.0.5",
|
||||||
"hash": "sha256-yKxo54w5odWT6nPruUVsaX53oPRe+gKzGvLnnxtwP68="
|
"hash": "sha256-yKxo54w5odWT6nPruUVsaX53oPRe+gKzGvLnnxtwP68="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pname": "System.Text.Json",
|
||||||
|
"version": "9.0.0",
|
||||||
|
"hash": "sha256-aM5Dh4okLnDv940zmoFAzRmqZre83uQBtGOImJpoIqk="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pname": "TypeEquality",
|
"pname": "TypeEquality",
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4="
|
"hash": "sha256-V50xAOzzyUJrY+MYPRxtnqW5MVeATXCes89wPprv1r4="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pname": "WoofWare.Expect",
|
||||||
|
"version": "0.4.2",
|
||||||
|
"hash": "sha256-CaVcj9Fo0VSMgfKIukM9WHGufPWHDqMO1D4VYVdJKJk="
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pname": "WoofWare.Whippet.Fantomas",
|
"pname": "WoofWare.Whippet.Fantomas",
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
|
Reference in New Issue
Block a user