使用netcat发送POST请求

24
我是一名有用的助手,可以为您翻译文本。

我在 PHP 中找到了一个小脚本,用于向 Twitter 发送简单的请求以更新您的状态。我尝试了这个脚本: http://pratham.name/twitter-php-script-without-curl.html,它起作用了。现在,我想用 netcat 发送这个请求,但这不起作用,为什么呢?

我是这样发送请求的:

echo -e $head | nc twitter.com 80

$head是我的标题,我已经尝试过PHP,所以它是正确的。

有人知道我怎么做吗?谢谢大家。

编辑。

head="POST http://twitter.com/statuses/update.json HTTP/1.1\r\n
Host: twitter.com\r\n
Authorization: Basic myname:passwordinbs64\r\n
Content-type: application/x-www-form-urlencoded\r\n
Content-length: 10\r\n
Connection: Close\r\n\r\n
status=mymessage";

echo -e $head | nc twitter.com 80

我们不是心灵读者。请链接脚本,并显示$head的内容。 - Matthew Flaschen
抱歉,我已经编辑了消息。 - fixo2020
谢谢,请您也展示一下如何初始化 $head。如果您有 curlwget,那可能会更容易些。 - Matthew Flaschen
先生,我现在不想使用curl或wget。 - fixo2020
我已经更新了我的答案,现在包含了解决方案。 - Mecki
2个回答

30

您发送的数据不正确。这是我执行的命令:

$ head="POST /statuses/update.json HTTP/1.1\r\n
Host: twitter.com\r\n
Authorization: Basic myname:passwordinbs64\r\n
Content-type: application/x-www-form-urlencoded\r\n
Content-length: 10\r\n
Connection: Close\r\n\r\n
status=mymessage"; echo $head  | nc twitter.com 80

HTTP/1.1 400 Bad Request
Date: Tue, 29 Jun 2010 10:19:38 GMT
Server: Apache
Vary: Accept-Encoding
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>

我同时运行了一个 tcpdump,这是它显示给我的:

0x0020:  5018 ffff 671f 0000 504f 5354 2068 7474  P...g...POST.htt
0x0030:  703a 2f2f 7477 6974 7465 722e 636f 6d2f  p://twitter.com/
0x0040:  7374 6174 7573 6573 2f75 7064 6174 652e  statuses/update.
0x0050:  6a73 6f6e 2048 5454 502f 312e 310d 0a20  json.HTTP/1.1...
0x0060:  486f 7374 3a20 7477 6974 7465 722e 636f  Host:.twitter.co
0x0070:  6d0d 0a20 4175 7468 6f72 697a 6174 696f  m...Authorizatio
0x0080:  6e3a 2042 6173 6963 206d 796e 616d 653a  n:.Basic.myname:
0x0090:  7061 7373 776f 7264 696e 6273 3634 0d0a  passwordinbs64..
0x00a0:  2043 6f6e 7465 6e74 2d74 7970 653a 2061  .Content-type:.a
0x00b0:  7070 6c69 6361 7469 6f6e 2f78 2d77 7777  pplication/x-www
0x00c0:  2d66 6f72 6d2d 7572 6c65 6e63 6f64 6564  -form-urlencoded
0x00d0:  0d0a 2043 6f6e 7465 6e74 2d6c 656e 6774  ...Content-lengt
0x00e0:  683a 2031 300d 0a20 436f 6e6e 6563 7469  h:.10...Connecti
0x00f0:  6f6e 3a20 436c 6f73 650d 0a0d 0a20 7374  on:.Close.....st
0x0100:  6174 7573 3d6d 796d 6573 7361 6765 0a    atus=mymessage.

你看到错误了吗?每个换行符都有三个字符,但实际上应该只有两个。这是因为你在变量定义中有一个真正的换行符,在shell中变成了一个空格。例如:

$ head="line1
line2" ; echo $head

line1 line2

尝试将所有代码写在一行中。

$ head="POST /statuses/update.json HTTP/1.1\r\nHost: twitter.com\r\nAuthorization: Basic myname:passwordinbs64\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length: 10\r\nConnection: Close\r\n\r\nstatus=mymessage" ; echo $head | nc twitter.com 80

HTTP/1.1 401 Unauthorized
Date: Tue, 29 Jun 2010 10:25:43 GMT
Server: hi
Status: 401 Unauthorized
X-Runtime: 0.00577
Content-Type: application/json; charset=utf-8
Content-Length: 63
Cache-Control: no-cache, max-age=300
Set-Cookie: k=194.145.236.196.1277807143945525; path=/; expires=Tue, 06-Jul-10 10:25:43 GMT; domain=.twitter.com
Set-Cookie: guest_id=1277807143950191; path=/; expires=Thu, 29 Jul 2010 10:25:43 GMT
Set-Cookie: _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCBOsPYMpAToHaWQiJWQzZDkxNTg2MTY3OTFk%250AMzg5OTUyNWFhZGZlZDY0YjJmIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--e95d14c755b85ff19606a0bc907c8b7a63d1b508; domain=.twitter.com; path=/
Expires: Tue, 29 Jun 2010 10:30:43 GMT
Vary: Accept-Encoding
Connection: close

{"errors":[{"code":32,"message":"Could not authenticate you"}]}

通常在发送HTTP请求时,第一行仅包含URI而不是完整的URL。这可能在规范中有说明,但我没有检查以确认,因此应该是head="POST /statuses/update.json HTTP/1.1\r\n - jcubic
@jcubic的说法很有道理,因为http://是多余的。当执行HTTP POST时,当然会使用HTTP协议。就像你现在正在与服务器通信一样清楚,为了区分不同的域,有HOST头字段。所以谢谢,我会相应地更新我的答案。然而,最初用户的问题确实是重复的换行符。 - Mecki
如果你引用它,它仍然是不正确的,因为每行末尾将会是\r\n\n。只有引用才能防止\n变成空格。 - Mecki
啊,那是因为我在编辑中忘记给echo添加“-e”开关了。 - αғsнιη
@αғsнιη -e,这实际上不是 POSIX 标准的一部分(因此除了 Bash shell 可能不支持它作为内置的 echo 命令外,系统的 /bin/echo 也可能不支持它),它只会让 Bash 对反斜杠转义字符进行解析,但它不会删除额外的换行符,所以最终你仍然在末尾拥有两个换行符。请参见http://tpcg.io/_S5STRY 。在第二种情况下,两行之间仍然有两个 0a - Mecki
对了,顺便提一下问题标签是 bash 而不是 POSIX,所以应该没问题。至于末尾换行符,也有 -n 开关可以使用。 - αғsнιη

10
如果您在"$head"周围不加引号,那么格式化将不会如您(或Twitter)所期望的那样。此外,由于您的变量包含换行符/回车符,抑制echo提供其自己的内容可能会有所帮助。
echo -ne "$head" | nc twitter.com 80

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接