http请求如何使用bash?

How to use bash for http request?

当我尝试使用 bash 进行 HTTP 请求时出现以下错误。有人知道如何解决这个问题吗?谢谢

$ exec 3<>/dev/tcp/httpbin.org/80
$ echo -e 'GET /get HTTP/1.1\r\nUser-Agent: bash\r\nAccept: */*\r\nAccept-Encoding: gzip\r\nhost: http://httpbin.org\r\nConnection: Keep-Alive\r\n\r\n' >&3
$ cat <&3
HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Wed, 31 Mar 2021 00:43:01 GMT
Content-Type: text/html
Content-Length: 524
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
</body>
</html>
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->
<!-- a padding to disable MSIE and Chrome friendly error page -->

您的 Host header 不正确。那应该是主机名,而不是 URL:

$ echo -e 'GET /get HTTP/1.1\r
User-Agent: bash\r
Accept: */*\r
Accept-Encoding: gzip\r
host: httpbin.org\r
Connection: Keep-Alive\r
\r
' >&3

这导致:

$ cat <&3
HTTP/1.1 200 OK
Date: Wed, 31 Mar 2021 00:55:23 GMT
Content-Type: application/json
Content-Length: 279
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    "User-Agent": "bash",
    "X-Amzn-Trace-Id": "Root=1-6063c87b-09303a470da318290e856d71"
  },
  "origin": "96.237.56.197",
  "url": "http://httpbin.org/get"
}

关于让脚本终止的第二个问题 正确地,一种选择是解析 Content-Length header 并且仅 读取那么多字节。类似于:

#!/bin/bash

exec 3<>/dev/tcp/httpbin.org/80

cat <<EOF | dos2unix >&3
GET /get HTTP/1.1
User-Agent: bash
host: httpbin.org

EOF

while :;  do
    read line <&3
    line=$(echo "$line" | tr -d '\r')
    [[ -z $line ]] && break

    if [[ $line =~ "Content-Length" ]]; then
        set -- $line
        content_length=
    fi
done

echo "length: $content_length"
dd bs=1 count=$content_length <&3 2> /dev/null

这适用于这个特定的测试用例,但它非常脆弱 (例如,如果没有 Content-Length header 怎么办?)。

我只想使用 curl 而不是尝试使用 bash 作为 http 客户.