2.17从 cURL 命令发送
推荐使用 ReqBin 在线测试和学习 cURL 命令,该网站提供大量可直接运行的 cURL 示例,调试 API 非常方便。
在与第三方 API 对接或调试时,cURL 命令是最常见的请求描述方式。框架内置了 cURL 命令解析引擎,支持从原生 cURL 命令字符串一键发起 HTTP 请求,覆盖常用选项(如 -X、-H、-d、-F、-u、--data-urlencode、--max-time、--http2 等),并可自由扩展自定义标志。
使用方式非常简单:将 cURL 命令直接传入 HttpRequestBuilder.FromCurl(),然后通过 IHttpRemoteService 发送即可。
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl("curl https://furion.net"));下面通过多个场景示例展示具体用法。
常规 GET 请求#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl("curl https://furion.net"));携带查询参数和 JSON 请求体#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddModel?query1=10&query2=hello' \ -H 'Content-Type: application/json' \ -d '{ "id": 1, "name": "sample" }' """));多部分表单(文件上传 + 普通字段)#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddForm?id=100' \ -F 'Id=100' \ -F 'Name=furion' \ -F 'File=@C:\Workspaces\httptest.jpg' """));文件上传使用 @ 前缀,路径支持本地绝对路径(如 C:\...)或网络 URL(如 @https://example.com/avatar.png)。
URL 编码表单(application/x-www-form-urlencoded)#
使用 -d 发送 URL 编码数据:
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddUrlForm' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'id=200&name=furion' """));使用 --data-urlencode 自动编码空格等特殊字符:
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddUrlForm' \ --data-urlencode 'id=200' \ --data-urlencode 'name=fu rion' """));单个文件上传#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddFile' \ -F 'file=@C:\Workspaces\httptest.jpg' """));多个文件上传#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/AddFiles' \ -F 'files=@C:\Workspaces\httptest.jpg' \ -F 'files=@C:\Workspaces\httptest.jpg' """));发送原始字符串(如 "This is a raw string")#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -k -X POST 'https://localhost:7044/HttpRemote/RawString' \ -H 'Content-Type: application/json' \ -d '"This is a raw string"' """));带有认证信息的请求#
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl(""" curl -X POST https://jsonplaceholder.typicode.com/posts \ -H "Content-Type: application/json" \ -u testuser:testpass \ -d '{"title":"Test"}' """));忽略输出选项(如 -o)#
某些 cURL 选项(如 -o、-v、-s)属于输出控制,不影响请求构建,会被自动忽略。例如:
var result = await httpRemoteService.SendAsStringAsync( HttpRequestBuilder.FromCurl("curl -o qr.png \"https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=Hello\""));该命令会正常发送 GET 请求并获取响应内容,但不会将结果保存为文件(文件保存需自行处理)。
扩展自定义 cURL 选项#
框架的 cURL 解析器采用可插拔提取器架构,每个 cURL 选项均由独立的 IHttpCurlExtractor 实现处理。您可以通过新增自定义提取器来支持私有 cURL 标志(如 --my-flag),而无需修改框架源码。
实现自定义提取器#
创建自定义提取器最便捷的方式是继承 HttpCurlExtractorBase 基类,它已封装好游标推进和参数消费逻辑:
/// <summary>/// 自定义 --my-flag 提取器/// </summary>internal sealed class CurlMyFlagExtractor : HttpCurlExtractorBase{ /// <summary> /// 匹配的标志集合(大小写不敏感) /// </summary> protected override string[] Flags => ["--my-flag"]; /// <summary> /// 是否需要参数。默认为 true;如果标志无需参数则设为 false。 /// </summary> protected override bool RequiresArgument => true; /// <summary> /// 当匹配到标志时执行的具体操作 /// </summary> /// <param name="httpRequestBuilder">请求构建器</param> /// <param name="flag">当前匹配的标志(已转为小写)</param> /// <param name="argument">携带的参数值,若无参数则为 null</param> protected override void Extract(HttpRequestBuilder httpRequestBuilder, string flag, string? argument) { // 此处根据标志设置构建器 if (!string.IsNullOrWhiteSpace(argument)) { // 示例:将参数值放入 X-My-Flag 请求头 httpRequestBuilder.WithHeader("X-My-Flag", argument); } }}对于更复杂的场景(如需要控制优先级、手动管理游标),可直接实现 IHttpCurlExtractor 接口;若需排序,则额外实现 IOrderedHttpCurlExtractor 接口(Order 越小优先级越高)。
注册自定义提取器#
自定义提取器在调用 FromCurl 时通过配置委托注入:
var builder = HttpRequestBuilder.FromCurl( "curl --my-flag hello-world http://example.com", options => options.AddExtractor(new CurlMyFlagExtractor()));如需移除内置提取器,可使用 options.RemoveExtractor<T>()。例如:
var builder = HttpRequestBuilder.FromCurl( "curl http://example.com", options => options.RemoveExtractor<CurlHeaderExtractor>());上下文对象说明#
HttpCurlParsingContext 提供了丰富的游标控制方法:
| 成员 | 说明 |
|---|---|
CurrentToken | 获取当前指向的 Token |
PeekNext() | 预览下一个 Token(不移动指针) |
Advance(count) | 向前推进指定步数(默认 1) |
CurrentTokenMatches(flags) | 检查当前 Token 是否匹配给定标志集合(忽略大小写) |
IsEndOfTokens | 是否已到达 Token 列表末尾 |
在直接实现 IHttpCurlExtractor 时,您需要自行调用 Advance 来消费 Token,否则会导致解析死循环。
参考实现#
框架内置的所有提取器(如 CurlMethodExtractor、CurlFormExtractor 等)均基于相同的接口和基类构建,您可以在仓库中查看其源码作为参考:查看内置提取器源码