$ cat file | curl -F 'sprunge=<-' http://sprunge.us
因此,输出echo
作为 POST 参数传递给 cURL。这是 cURL 的特定功能吗?
答案1
-
通常用于表示标准输入,并且<
通常用于表示从文件的重定向。我相信这些语法来自早期的 shell。它们一起意味着接受标准输入并将其发送/重定向到其他地方。语法几乎是自然的。
查看 cURL修订记录,该<
语法于 2000 年中期添加到 cURL 中。添加此功能的修订版可作为 Git commit 获得5b7a5046e6
。
从变更日志来看,
Torsten Foertsch <torsten.foertsch at gmx.net> brought a set of fixes for
the rfc1867 form posts. He introduced 'name=<file' which brings a means to
suuply very large text chunks read from the given file name. It differs from
'name=@file' in the way that this latter thing is marked in the uploaded
contents as a file upload, while the first is just text (as in a input or
textarea field). Torsten also corrected a bug that would happen if you used
%s or similar in a -F file name.
没有提及此功能的灵感或起源。
该@-
语法存在于我能找到的最早版本的源代码中的 cURL 中。从1999年底第一次修订以来,
/* postfield data */
if('@' == *nextarg) {
/* the data begins with a '@' letter, it means that a file name
or - (stdin) follows */
FILE *file;
nextarg++; /* pass the @ */
很难确定它是否是 cURL 特定的。语法常见且自然。与之关联的 cURL 特征是 cURL 的基本特征。如果是的话,类似于 cURL 的工具很可能会实现某种形式。
最初的问题是关于
$ echo foo | curl -d 'sprunge=<-' http://sprunge.us
这是我的回答:
我不认为这是 cURL 的功能。
$ # Terminal A
$ curl --version
curl 7.31.0 (x86_64-unknown-linux-gnu) libcurl/7.31.0 OpenSSL/1.0.1e zlib/1.2.8 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP
$
$ echo foo | curl -d 'sprunge=<-' localhost:2222
$ # Terminal B
$ nc -l 2222
POST / HTTP/1.1
User-Agent: curl/7.31.0
Host: localhost:2222
Accept: */*
Content-Length: 7
Content-Type: application/x-www-form-urlencoded
sprunge=<-
我在 cURL 文档中找不到任何提及此功能的信息。但也有类似的功能。
如果您以字母@开头数据,则其余部分应该是从中读取数据的文件名,或者 - 如果您希望curl从stdin读取数据。文件的内容必须已进行 URL 编码。也可以指定多个文件。因此,从名为“foobar”的文件发布数据可以使用 --data @foobar 来完成。
答案2
使用 socat 监视curl
有关此命令的更新问题:
$ cat file | curl -F 'sprunge=<-' http://sprunge.us
正在做几件事。使用socat
我们可以在一个终端中监视请求,如下所示:
$ socat - TCP4-LISTEN:2222,fork | grep -E 'Content-Disp|msg'
现在,在第二个终端中,我们将使用您的curl
命令连接到我们的socat
守护进程。对于cat file
我们将使用它作为我们的示例文件:
$ cat hello.txt
msg: hello curl
当我们curl
:
$ cat ~/hello.txt | curl -Fblah=\<- localhost:2222
我们在输出中看到这一点socat
:
Content-Disposition: form-data; name="blah"
msg: hello curl
如果我们将字符串从 a 更改blah
为 a,-
我们将看到以下内容:
$ cat ~/hello.txt | curl -F-=\<- localhost:2222
结果:
Content-Disposition: form-data; name="-"
正如我们所看到的,首字母后面的参数-F
是我们要提交的表单的名称。 -F`的手册页curl mentions that
用于提交一个 HTTP 表单,我们要在其中指定名称:
-F, --form <name=content>
(HTTP) This lets curl emulate a filled-in form in which a user
has pressed the submit button. This causes curl to POST data using
the Content-Type multipart/form-data according to RFC 2388.
This enables uploading of binary files etc. To force the 'content'
part to be a file, prefix the file name with an @ sign.
To just get the content part from a file, prefix the file
name with the symbol <. The difference between @ and < is then
that @ makes a file get attached in the post as a file upload,
while the < makes a text field and just get the contents for that
text field from a file.
该开关的其余开关-F-=
将 STDIN 输入连接到该参数。<-
。 STDIN 将包含通过cat file |
.
比较 args -'-F-=<-'
与-F-=\<-
这两个符号是相同的。我们可以再次使用额外的详细程度来查看发生了什么。
$ set -x; cat ~/hello.txt | curl '-F-=<-' localhost:2222; set +x
...
+ cat /Users/smingolelli/hello.txt
+ curl '-F-=<-' localhost:2222
而另一种方法:
$ set -x; cat ~/hello.txt | curl -F-=\<- localhost:2222; set +x
...
+ cat /Users/smingolelli/hello.txt
+ curl '-F-=<-' localhost:2222
人们喜欢使用第一种方法,因为它可以在键入时节省一个额外的字符。但从curl
的角度来看,它们是相同的。所做-F-=\<-
的就是转义重定向,以便curl
看到它而不是由 shell 处理它。
原始问题
最初的问题是关于这个的:
$ echo foo | curl -d 'sprunge=<-' http://sprunge.us
我对此的回答是:
当您使用卷曲开关时,-d
您暗示了手册页中的 POST curl
。
-d/--data <data>
(HTTP) Sends the specified data in a POST request to the HTTP server,
in the same way that a browser does when a user has filled in an
HTML form and presses the submit button. This will cause curl to pass
the data to the server using the content-type
application/x-www-form-urlencoded. Compare to -F/--form.