@@ -19,6 +19,40 @@ namespace A2A.Client;
1919public static class HttpClientExtensions
2020{
2121
22+ /// <summary>
23+ /// Sends a GET request to the specified URL and returns the HTTP response message
24+ /// </summary>
25+ /// <param name="client">The HttpClient instance</param>
26+ /// <param name="url">The request URL</param>
27+ /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
28+ /// <returns>The HTTP response message</returns>
29+ public static HttpResponseMessage Get ( this HttpClient client , Uri url , CancellationToken cancellationToken = default )
30+ {
31+ var request = new HttpRequestMessage ( HttpMethod . Get , url ) ;
32+ return client . Send ( request , cancellationToken ) ;
33+ }
34+
35+ /// <summary>
36+ /// Sends a GET request to the specified URL, expecting a JSON response, and deserializes it into the specified type
37+ /// </summary>
38+ /// <typeparam name="T">The type to deserialize the JSON response to</typeparam>
39+ /// <param name="client">The HttpClient instance</param>
40+ /// <param name="url">The request URL</param>
41+ /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
42+ /// <returns>The deserialized response object</returns>
43+ public static T ? GetFromJson < T > ( this HttpClient client , Uri url , CancellationToken cancellationToken = default )
44+ {
45+ var request = new HttpRequestMessage ( HttpMethod . Get , url ) ;
46+ request . Headers . Accept . Add ( new MediaTypeWithQualityHeaderValue ( MediaTypeNames . Application . Json ) ) ;
47+ var response = client . Send ( request , cancellationToken ) ;
48+ if ( response . IsSuccessStatusCode )
49+ {
50+ using var reader = new StreamReader ( response . Content . ReadAsStream ( cancellationToken ) , Encoding . UTF8 , leaveOpen : true ) ;
51+ return JsonSerializer . Deserialize < T > ( reader . ReadToEnd ( ) ) ;
52+ }
53+ else throw new HttpRequestException ( $ "Request failed with status code { response . StatusCode } ") ;
54+ }
55+
2256 /// <summary>
2357 /// Retrieves the A2A discovery document from a remote agent
2458 /// </summary>
@@ -85,4 +119,70 @@ public static Task<A2ADiscoveryDocument> GetA2ADiscoveryDocumentAsync(this HttpC
85119 return httpClient . GetA2ADiscoveryDocumentAsync ( request , cancellationToken ) ;
86120 }
87121
122+ /// <summary>
123+ /// Retrieves the A2A discovery document from a remote agent
124+ /// </summary>
125+ /// <param name="httpClient">The <see cref="HttpClient"/> to use to perform the request</param>
126+ /// <param name="request">The discovery request containing the base URI and optional configuration</param>
127+ /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
128+ /// <returns>The retrieved <see cref="A2ADiscoveryDocument"/></returns>
129+ public static A2ADiscoveryDocument GetA2ADiscoveryDocument ( this HttpClient httpClient , A2ADiscoveryDocumentRequest request , CancellationToken cancellationToken = default )
130+ {
131+ ArgumentNullException . ThrowIfNull ( httpClient ) ;
132+ ArgumentNullException . ThrowIfNull ( request ) ;
133+ try
134+ {
135+ var path = "/.well-known/agent.json" ;
136+ var endpoint = request . Address == null ? new Uri ( path , UriKind . Relative ) : new Uri ( request . Address , path ) ;
137+ var agentCard = httpClient . GetFromJson < AgentCard > ( endpoint , cancellationToken ) ;
138+ return new ( )
139+ {
140+ Endpoint = endpoint . IsAbsoluteUri ? endpoint : new ( httpClient . BaseAddress ! , path ) ,
141+ Agents = agentCard == null ? [ ] : [ agentCard ]
142+ } ;
143+ }
144+ catch ( HttpRequestException ex ) when ( ex . StatusCode == HttpStatusCode . NotFound )
145+ {
146+ var path = "/.well-known/agents.json" ;
147+ var endpoint = request . Address == null ? new Uri ( path , UriKind . Relative ) : new Uri ( request . Address , path ) ;
148+ var agentCards = httpClient . GetFromJson < List < AgentCard > > ( endpoint , cancellationToken ) ;
149+ return new ( )
150+ {
151+ Endpoint = endpoint . IsAbsoluteUri ? endpoint : new ( httpClient . BaseAddress ! , path ) ,
152+ Agents = agentCards ?? [ ]
153+ } ;
154+ }
155+ }
156+
157+ /// <summary>
158+ /// Retrieves the A2A discovery document from a remote agent
159+ /// </summary>
160+ /// <param name="httpClient">The <see cref="HttpClient"/> to use to perform the request</param>
161+ /// <param name="address">The base URI of the remote server to query for discovery metadata</param>
162+ /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
163+ /// <returns>The retrieved <see cref="A2ADiscoveryDocument"/></returns>
164+ public static A2ADiscoveryDocument GetA2ADiscoveryDocument ( this HttpClient httpClient , Uri address , CancellationToken cancellationToken = default )
165+ {
166+ ArgumentNullException . ThrowIfNull ( httpClient ) ;
167+ ArgumentNullException . ThrowIfNull ( address ) ;
168+ var request = new A2ADiscoveryDocumentRequest ( )
169+ {
170+ Address = address
171+ } ;
172+ return httpClient . GetA2ADiscoveryDocument ( request , cancellationToken ) ;
173+ }
174+
175+ /// <summary>
176+ /// Retrieves the A2A discovery document from a remote agent
177+ /// </summary>
178+ /// <param name="httpClient">The <see cref="HttpClient"/> to use to perform the request</param>
179+ /// <param name="cancellationToken">A <see cref="CancellationToken"/></param>
180+ /// <returns>The retrieved <see cref="A2ADiscoveryDocument"/></returns>
181+ public static A2ADiscoveryDocument GetA2ADiscoveryDocument ( this HttpClient httpClient , CancellationToken cancellationToken = default )
182+ {
183+ ArgumentNullException . ThrowIfNull ( httpClient ) ;
184+ var request = new A2ADiscoveryDocumentRequest ( ) ;
185+ return httpClient . GetA2ADiscoveryDocument ( request , cancellationToken ) ;
186+ }
187+
88188}
0 commit comments