首页 > 解决方案 > 如何使用 bash 进行 http 请求?

问题描述

当我尝试使用 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 -->

标签: bashhttptcp

解决方案


您的Host标题不正确。那应该是主机名,而不是 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标头并仅读取那么多字节。就像是:

#!/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=$2
    fi
done

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

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

我只是使用curl而不是尝试bash用作 http 客户端。


推荐阅读