正如 JSON 已经成为普遍的对象序列化格式一样,cURL 也应该是 HTTP 请求的普遍序列化格式。JSON 原本是为 JavaScript 使用的,其本名是 JavaScript Object Notation,但是各种语言都喜欢用它了,连 Java 这个强类型语言也总是要和它打交道——哪怕 JSON 里缺少类型信息以至于在 Java 中会碰到各种不便。
总之,JSON 已经成为了编程语言中的对象的非常受欢迎的序列化形式。
那么,对于 HTTP 请求,像 JSON 一样受欢迎的序列化形式,就应该是 cURL。
前情提要
《使用 cURL 提高前后端开发连调中的沟通效率 - Jeff Tian的文章 - 知乎》
《将 FeignClient 的请求记录成 cURL 格式 - Jeff Tian的文章 - 知乎》
《使用 jmeter 做压测,如何提供 cURL - Jeff Tian的文章 - 知乎》
《将 axios 的请求记录打印成 cURL - Jeff Tian的文章 - 知乎》
以上文章分别介绍了 NodeJs、Java 中如何将 HTTP 请求打印成 cURL 形式,今天再来聊一下在 C# 语言中,如何做同样的事情。
在 C# 中,往往是这样发送 HTTP 请求的:
csharp var request = new HttpRequestMessage(...); var response = await _client.SendAsync(request, cancellationToken);
在前面的 NodeJs 以及 Java 的文章里,我们都是用了请求拦截的方式,来获取到当前请求的配置,将将其序列化成 cURL。不过,在 C# 中,以上的代码示例展示了,其请求对象是在请求之前创建的,所以可以不用拦截请求,直接将请求对象进行序列化。
其实我本人觉得将请求对象序列化成 cURL,应该是一个内置对象。然而但是,并不存在这样的内置方法。
好在 C# 提供了一种扩展对象的机制,通过自定义一个扩展方法,最终在使用时,看起来就像是在调用一个内置方法。这个机制特别棒,不知道在 Java 中有没有类似的机制?
增加扩展方法
代码提交在 https://github.com/Jeff-Tian/leg-godt/commit/9044c5b36cb02b20ef03c44ef5b1bc5aa5d730e7 ,非常简单直接:
csharp using System.Text;
namespace Web;
public static class HttpRequestMessageExtensions
{
public async static Task
foreach (var header in request.Headers)
{
command.Append($-H {header.Key}: {string.Join(, , header.Value)} );
}
if (request.Content is not null)
{
var contentType = request.Content.Headers.ContentType?.MediaType;
if (contentType is not null)
{
command.Append($-H Content-Type: {contentType} );
}
var content = await request.Content.ReadAsStringAsync();
command.Append($-d {content} );
}
return command.ToString();
}
}
使用效果
代码见 https://github.com/Jeff-Tian/leg-godt/commit/4fdea567b2045e9cb60bf07741b1b3da6b023497 ,主要是:
csharp public async Task<OneOf<Success, Error>> Handle(StrapiEntry body, CancellationToken cancellationToken) { _logger.LogInformation(Received Strapi webhook request to {Event} with {Model}: {FullName}, body.Event, body.Model, body.Entry.Full_name); var yuqueToken = _configuration[YuQue:Token]; Debug.Assert(yuqueToken is not null); var request = new HttpRequestMessage(HttpMethod.Post, https://api.yuque.com/v2/repos/tian-jie/docs); request.Headers.Authorization = new AuthenticationHeaderValue(Bearer, yuqueToken); request.Content = JsonContent.Create(new Dictionary<string, object> { { title, body.Entry.Full_name }, { body, $Created at {body.Entry.CreatedAt} }, { format, markdown }, { public, 0 }, });
_logger.LogInformation(Sending Yuque request:n{CurlCommand}, await request.ToCurlCommand());
var response = await _client.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
打印出来就是:
彩蛋
以上示例是故意尝试调用语雀 API,但却是以一种错误的方式,所以得到了一个 Forbidden 的结果。要正常调用语雀 API,可以参考其官方文档:https://www.yuque.com/yuque/developer/openapi 。
不过,官方文档上虽然上传了一个 Swagger API 文档,但是还得自己下载后用工具查看,非常不方便。我这里将它上传到了 Swagger Hub,以供大家直接使用: https://app.swaggerhub.com/apis/Jeff-Tian/yuque-open_api/2.0.1
当然,要在线上调通的话,需要执行请求之前,将个人 Token 填好:
希望帮到你节约了几分钟的时间!