curl --request(-X):为 HTTP/FTP/POP3/IMAP/SMTP 指定自定义请求方法
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
--request(短选项-X)是 curl 命令行中用于替换默认请求方法/命令的通用开关:在 HTTP 下它改变请求行中的方法词(默认为GET),在 FTP、POP3、IMAP、SMTP 下则分别替换LIST、RETR、HELP等默认命令。本文以 docs/cmdline-opts/request.md 为主线,结合本仓库 curl 源码,完整讲解该选项的语法、跨协议行为、与重定向/专用选项的交互,以及 libcurl 层面的CURLOPT_CUSTOMREQUEST对应实现,帮助你准确、安全地使用自定义请求方法。
一、选项概览:语法与元信息
--request的完整定义记录在 docs/cmdline-opts/request.md 的 YAML 头中,可归纳为:
| 字段 | 值 | 说明 |
|---|---|---|
| 长选项 | --request | 完整写法 |
| 短选项 | -X | 简写 |
| 参数 | <method> | 要使用的请求方法/命令字符串 |
| 帮助文本 | Specify request method to use | 指定要使用的请求方法 |
| 适用类别 | connection、pop3、ftp、imap、smtp | 覆盖连接层及四种邮件/文件传输协议 |
| 引入版本 | 6.0(命令行文档层面) | 协议子能力有各自引入时间(见后文) |
| Multi | single | 单次调用只允许指定一个方法,重复使用后者覆盖前者 |
文档内置的两个示例即覆盖了 HTTP 与 FTP 两种典型用法:
--request "DELETE" $URL -X NLST ftp://example.com/在命令行的参数解析层,该选项注册于 src/tool_getparam.c:{"request", ARG_STRG, 'X', C_REQUEST}将后续参数解析为字符串存入config->customrequest,并使用DENY_BLANK校验规则——即空白参数会被拒绝(PARAM_BLANK_STRING)。传入的方法字符串最终保存在struct OperationConfig的customrequest字段中(见 src/tool_cfgable.h)。
二、核心行为:verbatim 原样传递,不做任何过滤
--request最容易被忽视、也最需要警惕的特性是:curl 会把用户提供的字符串逐字(verbatim)放进请求,不做过滤、不做安全防护,包括空白字符和控制字符。
文档原文明确写道:
curl passes on the verbatim string you give it in the request without any filter or other safe guards. That includes white space and control characters.
这意味着:
- 方法字符串中的空格会被原样发送,可能改变 HTTP 请求行的解析结果或 FTP/邮件协议命令的参数结构;
- 控制字符同样不会被拦截,存在被注入到协议命令中的风险;
- 在 POP3/IMAP 实现中,自定义命令在进入协议之前会经过 URL 解码处理:POP3 侧为 lib/pop3.c 的
pop3_parse_custom_request(),IMAP 侧为 lib/imap.c 的imap_parse_custom_request(),其中 IMAP 的解码使用REJECT_CTRL标志拒绝包含控制字符的输入——这是协议层面对“逐字传递”策略的必要兜底。
因此在使用--request时,务必只传入自己完全信任、来源受控的方法字符串,不要拼接未经验证的外部输入。
三、HTTP:自定义请求方法
3.1 它改变什么、不改变什么
对 HTTP 而言,--request指定的是与服务器通信时使用的自定义请求方法,用于替代默认的GET。文档建议参考 HTTP/1.1 规范获取完整方法集合,常见的补充方法包括PUT、DELETE,以及 WebDAV 相关技术提供的PROPFIND、COPY、MOVE等。
关键在于:该选项只改变请求行里的那个“动词”单词,不改变 curl 自身的行为方式。例如:
-X HEAD并不等于真正的 HEAD 请求,正确的做法是使用--head(-I)选项;-X POST不会自动附带请求体,发送请求体需要--data(-d)等配套选项。
curl 命令行工具自身会对这种误用给出提示。在 src/tool_helpers.c 的customrequest_helper()中实现了两套警告逻辑:
- 当
--request指定的方法与已推断出的默认方法相同(例如用-d发了 POST 又写-X POST),会提示Unnecessary use of -X or --request, POST is already inferred.; - 当把方法设为
head时,会警告Setting custom HTTP method to HEAD with -X/--request may not work the way you want. Consider using -I/--head instead.
3.2 默认方法从何而来
customrequest_helper()中的默认方法表(与 src/tool_sdecls.h 的HttpReq枚举一一对应)揭示了专用选项与默认方法的映射关系:
GET / GET / HEAD / POST / POST / PUT对应关系即:未指定时为GET,--head对应HEAD,--data/--form对应POST,--upload-file对应PUT。文档强调:常规的 GET、HEAD、POST、PUT 请求不需要--request,直接使用对应的专用命令行选项即可,既语义清晰又能让 curl 正确处理请求体、响应处理等行为。
3.3 与重定向(--location / --follow)的交互
文档明确指出一个高风险场景:
If
--locationis used, the method string you set with--requestis used for all requests, which may cause unintended side-effects when curl does not change request method according to the HTTP 30x response codes.
即:一旦配合--location(别名--follow)跟随 30x 重定向,你设置的自定义方法会应用于所有请求,而 curl 原本依据 HTTP 30x 响应码切换请求方法的逻辑(如 301/302 后 POST 改 GET)不会自动生效,可能产生意外副作用。
源码印证了这一行为。在 lib/http.c 的http_switch_to_get()中:
static void http_switch_to_get(struct Curl_easy *data, int code) { const char *req = CURL_EASY_STR(data, STRING_CUSTOMREQUEST); if((req ||>cmd = curl_maprintf("%s%s%.*s", CURL_EASY_STR(data, STRING_CUSTOMREQUEST) ? CURL_EASY_STR(data, STRING_CUSTOMREQUEST) : (data->state.list_only ? "NLST" : "LIST"), lstArg ? " " : "", lstArglen, lstArg ? lstArg : "");即在设置了自定义命令时直接采用用户字符串,否则按list_only标志选择NLST或LIST。同理,在启用 PRET(用于防火墙后 PASV 准备)时,lib/ftp.c 也会优先采用自定义命令。
需要注意:替换的是列表命令,而非上传/下载传输命令;同时方法字符串同样是逐字传递,应避免在其中夹带无关参数。
五、POP3 / IMAP / SMTP:自定义邮件协议命令
5.1 POP3
--request可指定自定义 POP3 命令,替代默认的LIST(列邮件)或RETR(取邮件),该能力自 7.26.0 起提供。自定义命令会经过 URL 解码后用于协议交互(见 lib/pop3.c 的pop3_parse_custom_request())。典型场景如直接向服务器发送STAT、UIDL等命令:
# 以自定义命令替代默认行为 curl --request STAT pop3://mail.example.com/ curl -X "UIDL" pop3://mail.example.com/5.2 IMAP
--request可指定自定义 IMAP 命令,替代默认的LIST,自 7.30.0 起提供。同样地,lib/imap.c 会对自定义命令做 URL 解码,并用REJECT_CTRL拒绝控制字符,随后作为 IMAP 命令发送:
# 查询邮箱状态 curl --request "STATUS INBOX (MESSAGES)" imap://mail.example.com/INBOX5.3 SMTP
--request可指定自定义 SMTP 命令,替代默认的HELP或VRFY,自 7.34.0 起提供。例如验证邮箱地址是否存在:
# 以 VRFY 替代默认 HELP curl -X "VRFY user@example.com" smtp://mail.example.com/三个协议的共同点是:--request改变的是协议命令词,而 curl 对该协议的传输框架(认证、TLS、收尾等)保持不变,因此适合在默认命令之外向服务器发出额外查询类命令。
六、libcurl 编程接口:CURLOPT_CUSTOMREQUEST
命令行--request在底层映射为 libcurl 的CURLOPT_CUSTOMREQUEST选项。在 src/config2setopts.c 中可以看到命令行工具向 libcurl 的传递过程:
MY_SETOPT_STR(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); customrequest_helper(config->httpreq, config->customrequest);CURLOPT_CUSTOMREQUEST同样在 lib/easyoptions.c 中以CURLOT_STRING注册。使用 C 接口时等价写法为:
CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "https://api.example.com/resource/42"); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_perform(curl); curl_easy_cleanup(curl);与命令行一致,该选项的值也会被逐字放入请求,同样需要自行保证内容安全。
若需要查询最终实际生效的方法,可通过CURLINFO_EFFECTIVE_METHOD获取。lib/getinfo.c 展示了其取值逻辑:优先返回自定义方法;未设置时若opt_no_body为真则返回HEAD,否则返回GET。命令行下配合--trace或-v也可以直观看到实际发出的请求行。
七、配套选项:--request-target
与--request常搭配使用的是 docs/cmdline-opts/request-target.md 中定义的--request-target(7.55.0 起,仅 HTTP):它用备选路径替代 URL 中的路径,用于发出不符合常规 URL 模式的目标,典型例子是 HTTP 规范中的OPTIONS *:
curl --request-target "*" -X OPTIONS $URL--request负责改写请求行的方法词,--request-target负责改写请求行的目标(路径)部分,两者组合可构造几乎任意形态的 HTTP 请求行;同样地,--request-target的值也是逐字传递、不加过滤。
八、实践建议总结
| 场景 | 正确做法 | 说明 |
|---|---|---|
| 普通 GET/HEAD/POST/PUT | 使用-G/-I/-d/-T等专用选项 | 避免-X,方法推断更安全,行为更完整 |
| 自定义 HTTP 方法(DELETE、PATCH、WebDAV 等) | --request <method> | 只改方法词,不改变 curl 行为 |
| 发送真正的 HEAD 请求 | --head | -X HEAD不完整,会收到响应体 |
| 自定义方法 + 跟随重定向 | 谨慎评估--location/--follow的副作用 | 自定义方法会作用于所有请求,30x 方法切换逻辑可能被绕过 |
| FTP/POP3/IMAP/SMTP 自定义协议命令 | --request <command> | 分别替代LIST/RETR/LIST/HELP等默认命令 |
| 构建非常规请求行 | --request+--request-target | 例如OPTIONS * |
| 排查实际发送内容 | -v或--trace | 观察真实请求行与命令 |
最后再次强调安全底线:--request的字符串会被逐字放入协议流量,只应传入受信任的静态方法名,切勿直接拼接用户输入。源码级佐证可继续查看 src/tool_getparam.c、src/tool_helpers.c、lib/http.c、lib/ftp.c、lib/pop3.c 与 lib/imap.c 等实现文件。
【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考