/// <summary> /// 异步执行一个 GET 请求。 /// </summary> /// <param name="httpClient"></param> /// <param name="relativePath"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <IHttpResponse> GetTextAsync(this IHttpClient httpClient, string relativePath, CancellationToken cancellationToken = default) { IHttpRequest request = httpClient .Create(HttpMethods.GET, relativePath) .AddHeader("Accept", "text/plain"); return(await httpClient.ExecuteAsync(request, cancellationToken)); }
/// <summary> /// 以文本的数据传递方式,异步执行一个 DELETE 请求。 /// </summary> /// <param name="httpClient"></param> /// <param name="relativePath"></param> /// <param name="data"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <IHttpResponse> DeleteTextAsync(this IHttpClient httpClient, string relativePath, string data = null, CancellationToken cancellationToken = default) { IHttpRequest request = httpClient .Create(HttpMethods.DELETE, relativePath) .AddHeader("Accept", "text/plain") .AddHeader("Content-Type", "text/plain") .SetBody(data); return(await httpClient.ExecuteAsync(request, cancellationToken)); }
/// <summary> /// 以 XML 的数据传递方式,异步执行一个 PUT 请求。 /// </summary> /// <param name="httpClient"></param> /// <param name="relativePath"></param> /// <param name="data"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <IHttpResponse> PutXmlAsync(this IHttpClient httpClient, string relativePath, object data = null, CancellationToken cancellationToken = default) { IHttpRequest request = httpClient .Create(HttpMethods.PUT, relativePath) .AddHeader("Accept", "application/xml") .AddHeader("Content-Type", "application/xml") .SetBody(SerializeObjectToXML(data)); return(await httpClient.ExecuteAsync(request, cancellationToken)); }
/// <summary> /// 以 JSON 的数据传递方式,异步执行一个 PATCH 请求。 /// </summary> /// <param name="httpClient"></param> /// <param name="relativePath"></param> /// <param name="data"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <IHttpResponse> PatchJsonAsync(this IHttpClient httpClient, string relativePath, object data = null, CancellationToken cancellationToken = default) { IHttpRequest request = httpClient .Create(HttpMethods.PATCH, relativePath) .AddHeader("Accept", "application/json") .AddHeader("Content-Type", "application/json") .SetJsonBody(data); return(await httpClient.ExecuteAsync(request, cancellationToken)); }
public async Task HttpGetTest() { using (IHttpClient httpClient = GetHttpClient()) { IHttpResponse response = await httpClient.GetTextAsync("search?q=hello+world"); Assert.Equal(200, response.StatusCode); } using (IHttpClient httpClient = GetHttpClient()) { IHttpRequest request = httpClient .Create(HttpMethods.GET, "search") .AddQueryString("q", "hello world"); IHttpResponse response = await httpClient.ExecuteAsync(request); Assert.Equal(200, response.StatusCode); } }
/// <summary> /// 基于指定策略执行指定的 HTTP 请求。 /// </summary> /// <typeparam name="TResponse"></typeparam> /// <param name="httpClient"></param> /// <param name="httpRequest">HTTP 请求。</param> /// <param name="policy">策略。</param> /// <param name="cancellationToken"></param> /// <returns></returns> /// <exception cref="HttpRequestException"></exception> /// <exception cref="HttpTimeoutException"></exception> public static async Task <IHttpResponse> ExecuteAsync <TResponse>(this IHttpClient httpClient, IHttpRequest httpRequest, IAsyncPolicy <TResponse> policy, CancellationToken cancellationToken = default(CancellationToken)) where TResponse : class, IHttpResponse { if (httpRequest == null) { throw new ArgumentNullException(nameof(httpRequest)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } void Clone(IHttpRequest src, ref IHttpRequest dest) { dest.Method = src.Method; dest.Credentials = src.Credentials; if (src.RequestUri == null) { dest.RequestUri = null; } else { dest.RequestUri = new Uri(src.RequestUri.ToString(), src.RequestUri.IsAbsoluteUri ? UriKind.Absolute : UriKind.RelativeOrAbsolute); } if (src.Body == null) { src.SetBody(string.Empty); } else { int len = src.Body.Length; dest.Body = new byte[len]; Buffer.BlockCopy(src.Body, 0, dest.Body, 0, len); } dest.Headers.Clear(); foreach (HttpHeader header in src.Headers) { dest.Headers.Add(header); } } IHttpRequest httpRequestCopy = httpClient.Create(httpRequest.Method); try { return(await policy .WrapAsync(Policy.TimeoutAsync(httpClient.Timeout)) .ExecuteAsync((innerCancellationToken) => { /* * 使用浅表克隆的方式,以确保在重试策略下不对原始 IHttpRequest 对象造成污染。 */ Clone(httpRequest, ref httpRequestCopy); return httpClient.ExecuteAsync(httpRequestCopy, innerCancellationToken) as Task <TResponse>; }, cancellationToken)); } catch (Polly.Timeout.TimeoutRejectedException ex) { throw new HttpTimeoutException("Time out during retry.", ex); } catch (OperationCanceledException ex) { throw new HttpTimeoutException("Time out.", ex); } finally { Clone(httpRequestCopy, ref httpRequest); } }