Open kosh04 opened 8 years ago
xyzzyの実装は正しくて、コネクション自体が終わっていない(HTTP 1.1はデフォルトでkeep-aliveになっているから)だけではないでしょうか。 (yahoo はkeep-aliveを実装していない?)
(format stream "GET / HTTP/1.1\n")
を (format stream "GET / HTTP/1.0\n")
にするか、GETの後に
(format stream "Connection: close\n")
を付ければ、リクエスト毎にコネクションが切断されるようになって、所望の結果が得られるのではないかと思います。
確かにコネクションを切断するように指定すれば上のコードはうまく動作するみたいですね。ありがとうございます。
ただ、サイトによっては実行中に別の問題が発生するみたいです。 例えば httpbin.org では
(with-open-stream (stream (connect "httpbin.org" "https" :ssl t))
(format stream "GET /ip HTTP/1.1\n")
(format stream "Host: httpbin.org\n")
(format stream "Connection: close\n")
(format stream "\n")
(let (line)
(while (setq line (read-line stream nil))
(insert line "\n"))))
;;-> 通信内容が出力される
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 14 Jan 2016 18:49:00 GMT
Content-Type: application/json
Content-Length: 31
Connection: close
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
"origin": "127.0.0.1"
}
;; エラーメッセージ: Disconnect: 指定されたハンドルが無効です
*Trace Output*
バッファを見ると「DecryptMessage (context expired): このコンテキストは、期限が切れているので使用できません。 」と出力されていて、read-line 関数の読み込み途中にSSLソケットストリームが無効になる(?)ようなエラーが発生してしまうため、解決したとは言いがたい状態です…。
どうも、src/sockssl.cc
内の sockssl::decrypt_data()
で、DecryptMessage()
が返すSEC_I_CONTEXT_EXPIRED
をエラーとして扱っているのが原因のようです。
他のソフトをいくつか見てみましたが、無視してセッションクローズしてしまうのが正しい?
件のサイトでもエラーが出ないようなパッチを作ってみましたが、Windowsはよく分かっていないのでこれでいいのかどうか。
パッチを当てて再ビルドしてみたら通りました :+1:
改善の余地はありそうですが、一応このパッチはPull Requestとして投げてみてはどうでしょうか。
xyzzy 0.2.2.248 リリースノート に書かれている SSL クライアントのサンプルコードを実行すると、ストリームの終端の受信待ちから先に進まずプログラムが応答しなくなるようです。
(connect "www.google.co.jp" "http")
に差し替えても同じ挙動になります。ただし、HTTPS ポートを開いていない
www.yahoo.co.jp
の http 接続は問題ありませんでした。