web-dev-qa-db-ja.com

既存のTCP接続でbashスクリプトからhttpサーバーにアクセスする方法は?

Bash Shell sciptでは、いくつかのコマンドラインツール(wgetcurlhttpie)を使用してhttpサーバーをテストします。

使用する場合curlでGETリクエストを呼び出すと、tcp接続がサーバーに対して開かれ、http通信が完了した直後に閉じられます。

$ curl http://10.5.1.1/favicon.ico -o /dev/null 

サーバーのキープアライブ動作をより適切にテストするために、複数のhttp要求/応答サイクルにわたってtcp接続を開いたままにしておきたいです。

次のようにbashから直接貧弱なhttpリクエストを実行できます。

exec 3<>/dev/tcp/10.5.1.1/80
printf "GET /\r\n\r\n" >&3
while IFS= read -r -u3 -t2 line || [[ -n "$line" ]]; do echo "$line"; done
exec 3>&-
exec 3<&-

しかし、私のテスト通信ははるかに複雑なため(認証など)、これを完全にbashまたは他のスクリプト言語で自分でコーディングするのではなく、既存のツールを使用したいと考えています。アイデアは、最初にbashでtcpソケットを開き、次にいくつかのコマンドラインツールに、独自のソケットを開く代わりにこの接続を使用するように強制することです。多分このように;

exec 3<>/dev/tcp/10.5.1.1/80
curl http://10.5.1.1/message.txt --use-existing-socket-fd=3
# ... do some other testing stuff ...
wget http://10.5.1.1/message.txt --use-existing-socket-fd=3
# ... do some other testing stuff ...
http http://10.5.1.1/message.txt --use-existing-socket-fd=3
exec 3>&-
exec 3<&-

これは、上記のツールを使用して、または他のツールを使用して可能ですか?

3
Joe

お探しのツールはsocatです。 1つのWebサーバーをテストしているので、そのサーバーへの永続的な接続を確立するように要求できます(サーバーが閉じることを選択しない限り、タイムアウトを調整します)。これが完了すると、トンネルとしての接続。これを実現する2つの方法を次に示します。

Unixソケットを介したクエリ

curlには--unix-socketオプションを使用すると、UNIXソケットを介してHTTP要求を送信し、HTTP応答を受信できます(啓発的なコメントをありがとう)

次のように使用します。

socat TCP:10.5.1.1:80 UNIX-LISTEN:/tmp/curl.sock,fork

次に、別の端末で:

curl --unix-socket /tmp/curl.sock http://10.5.1.1/message1.txt
curl --unix-socket /tmp/curl.sock http://10.5.1.1/message2.txt
...

疑似HTTPプロキシを介したクエリ

トンネルを、wgetcurl、...が接続する疑似プロキシとして利用できるようにすることもできます。このソリューションには、curlに限定されないという利点があります。

今回は、socatがローカルのTCPポートをリッスンします(たとえば3128)):

socat TCP:10.5.1.1:80 TCP-LISTEN:3128,fork,reuseaddr

次に、別の端末で:

export http_proxy='http://localhost:3128'
curl http://10.5.1.1/message.txt
wget http://10.5.1.1/message.txt
....

HTTPクライアントはプロキシを使用しているため、HTTPリクエストはわずかに変更され、これは望ましくない場合があります。

もちろん、これらの2つのソリューションはいずれも、複数のHTTPサーバーで使用することを意図したものではありません。これは、すべての要求を受信するチャネルの最後にあるWebサーバーだからです。

4
xhienne