Be more forgiving about the source of the attributes (#129)

This commit is contained in:
Patrick Stevens
2024-04-29 20:46:14 +01:00
committed by GitHub
parent 09780efb07
commit c51038448a
6 changed files with 107 additions and 8 deletions

View File

@@ -1140,6 +1140,69 @@ module ApiWithHeaders =
member _.SomeHeader : string = someHeader () member _.SomeHeader : string = someHeader ()
member _.SomeOtherHeader : int = someOtherHeader () member _.SomeOtherHeader : int = someOtherHeader ()
member this.GetPathParam (parameter : 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.Web.HttpUtility.UrlEncode),
System.UriKind.Relative
)
)
let httpMessage =
new System.Net.Http.HttpRequestMessage (
Method = System.Net.Http.HttpMethod.Get,
RequestUri = uri
)
do httpMessage.Headers.Add ("X-Foo", this.SomeHeader.ToString ())
do httpMessage.Headers.Add ("Authorization", this.SomeOtherHeader.ToString ())
do httpMessage.Headers.Add ("Header-Name", "Header-Value")
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 ApiWithHeaders2 =
/// Create a REST client. The input functions will be re-evaluated on every HTTP request to obtain the required values for the corresponding header properties.
let make
(someHeader : unit -> string)
(someOtherHeader : unit -> int)
(client : System.Net.Http.HttpClient)
: IApiWithHeaders2
=
{ new IApiWithHeaders2 with
member _.SomeHeader : string = someHeader ()
member _.SomeOtherHeader : int = someOtherHeader ()
member this.GetPathParam (parameter : string, ct : CancellationToken option) = member this.GetPathParam (parameter : string, ct : CancellationToken option) =
async { async {
let! ct = Async.CancellationToken let! ct = Async.CancellationToken

View File

@@ -142,3 +142,16 @@ type IApiWithHeaders =
[<Get "endpoint/{param}">] [<Get "endpoint/{param}">]
abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string> abstract GetPathParam : [<Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>
[<WoofWare.Myriad.Plugins.HttpClient>]
[<WoofWare.Myriad.Plugins.RestEase.Header("Header-Name", "Header-Value")>]
type IApiWithHeaders2 =
[<WoofWare.Myriad.Plugins.RestEase.Header "X-Foo">]
abstract SomeHeader : string
[<WoofWare.Myriad.Plugins.RestEase.Header "Authorization">]
abstract SomeOtherHeader : int
[<Get "endpoint/{param}">]
abstract GetPathParam :
[<WoofWare.Myriad.Plugins.RestEase.Path "param">] parameter : string * ?ct : CancellationToken -> Task<string>

View File

@@ -50,10 +50,14 @@ module RestEase =
/// Indicates that this interface member causes the interface to set a header with the given name, /// Indicates that this interface member causes the interface to set a header with the given name,
/// whose value is obtained whenever required by a fresh call to the interface member. /// whose value is obtained whenever required by a fresh call to the interface member.
type HeaderAttribute (header : string) = type HeaderAttribute (header : string, value : string option) =
inherit Attribute () inherit Attribute ()
new (header : string) = HeaderAttribute (header, None)
new (header : string, value : string) = HeaderAttribute (header, Some value)
/// Indicates that this argument to a method is interpolated into the request path at runtime /// Indicates that this argument to a method is interpolated into the request path at runtime
/// by writing it into the templated string that specifies the HTTP query e.g. in the `[<Get "/foo/{template}">]`. /// by writing it into the templated string that specifies the HTTP query e.g. in the `[<Get "/foo/{template}">]`.
type PathAttribute () = type PathAttribute (path : string option) =
inherit Attribute () inherit Attribute ()
new (path : string) = PathAttribute (Some path)
new () = PathAttribute None

View File

@@ -29,12 +29,16 @@ WoofWare.Myriad.Plugins.RestEase+GetAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+HeadAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+HeadAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+HeadAttribute..ctor [constructor]: string WoofWare.Myriad.Plugins.RestEase+HeadAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+HeaderAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string option)
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: (string, string)
WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: string WoofWare.Myriad.Plugins.RestEase+HeaderAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+OptionsAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+OptionsAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+OptionsAttribute..ctor [constructor]: string WoofWare.Myriad.Plugins.RestEase+OptionsAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PatchAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+PatchAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PatchAttribute..ctor [constructor]: string WoofWare.Myriad.Plugins.RestEase+PatchAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PathAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+PathAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: string option
WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: unit WoofWare.Myriad.Plugins.RestEase+PathAttribute..ctor [constructor]: unit
WoofWare.Myriad.Plugins.RestEase+PostAttribute inherit System.Attribute WoofWare.Myriad.Plugins.RestEase+PostAttribute inherit System.Attribute
WoofWare.Myriad.Plugins.RestEase+PostAttribute..ctor [constructor]: string WoofWare.Myriad.Plugins.RestEase+PostAttribute..ctor [constructor]: string

View File

@@ -1,5 +1,5 @@
{ {
"version": "2.3", "version": "3.0",
"publicReleaseRefSpec": [ "publicReleaseRefSpec": [
"^refs/heads/main$" "^refs/heads/main$"
], ],

View File

@@ -1,8 +1,6 @@
namespace WoofWare.Myriad.Plugins namespace WoofWare.Myriad.Plugins
open System
open System.Net.Http open System.Net.Http
open System.Text
open Fantomas.FCS.Syntax open Fantomas.FCS.Syntax
open Fantomas.FCS.SyntaxTrivia open Fantomas.FCS.SyntaxTrivia
open Fantomas.FCS.Xml open Fantomas.FCS.Xml
@@ -143,7 +141,8 @@ module internal HttpClientGenerator =
|> List.choose (fun attr -> |> List.choose (fun attr ->
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "Header" | "Header"
| "RestEase.Header" -> | "RestEase.Header"
| "WoofWare.Myriad.Plugins.RestEase.Header" ->
match attr.ArgExpr with match attr.ArgExpr with
| SynExpr.Paren (SynExpr.Tuple (_, [ v1 ; v2 ], _, _), _, _, _) -> | SynExpr.Paren (SynExpr.Tuple (_, [ v1 ; v2 ], _, _), _, _, _) ->
Some [ SynExpr.stripOptionalParen v1 ; SynExpr.stripOptionalParen v2 ] Some [ SynExpr.stripOptionalParen v1 ; SynExpr.stripOptionalParen v2 ]
@@ -725,6 +724,10 @@ module internal HttpClientGenerator =
attrs attrs
|> List.choose (fun attr -> |> List.choose (fun attr ->
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "RestEase.Query"
| "RestEase.QueryAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Query"
| "WoofWare.Myriad.Plugins.RestEase.QueryAttribute"
| "Query" | "Query"
| "QueryAttribute" -> | "QueryAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -733,6 +736,10 @@ module internal HttpClientGenerator =
Some (HttpAttribute.Query (Some s)) Some (HttpAttribute.Query (Some s))
| SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Query attribute: %+A{a}" | SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Query attribute: %+A{a}"
| _ -> None | _ -> None
| "RestEase.Path"
| "RestEase.PathAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Path"
| "WoofWare.Myriad.Plugins.RestEase.PathAttribute"
| "Path" | "Path"
| "PathAttribute" -> | "PathAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -741,6 +748,10 @@ module internal HttpClientGenerator =
| SynExpr.Const (SynConst.Unit, _) -> Some (HttpAttribute.Path PathSpec.MatchArgName) | SynExpr.Const (SynConst.Unit, _) -> Some (HttpAttribute.Path PathSpec.MatchArgName)
| SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Path attribute: %+A{a}" | SynExpr.Const (a, _) -> failwith $"unrecognised constant arg to the Path attribute: %+A{a}"
| _ -> None | _ -> None
| "RestEase.Body"
| "RestEase.BodyAttribute"
| "WoofWare.Myriad.Plugins.RestEase.Body"
| "WoofWare.Myriad.Plugins.RestEase.BodyAttribute"
| "Body" | "Body"
| "BodyAttribute" -> | "BodyAttribute" ->
match attr.ArgExpr with match attr.ArgExpr with
@@ -756,8 +767,10 @@ module internal HttpClientGenerator =
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "BasePath" | "BasePath"
| "RestEase.BasePath" | "RestEase.BasePath"
| "WoofWare.Myriad.Plugins.RestEase.BasePath"
| "BasePathAttribute" | "BasePathAttribute"
| "RestEase.BasePathAttribute" -> Some attr.ArgExpr | "RestEase.BasePathAttribute"
| "WoofWare.Myriad.Plugins.RestEase.BasePathAttribute" -> Some attr.ArgExpr
| _ -> None | _ -> None
) )
@@ -767,8 +780,10 @@ module internal HttpClientGenerator =
match attr.TypeName.AsString with match attr.TypeName.AsString with
| "BaseAddress" | "BaseAddress"
| "RestEase.BaseAddress" | "RestEase.BaseAddress"
| "WoofWare.Myriad.Plugins.RestEase.BaseAddress"
| "BaseAddressAttribute" | "BaseAddressAttribute"
| "RestEase.BaseAddressAttribute" -> Some attr.ArgExpr | "RestEase.BaseAddressAttribute"
| "WoofWare.Myriad.Plugins.RestEase.BaseAddressAttribute" -> Some attr.ArgExpr
| _ -> None | _ -> None
) )