お初にお目にかかります。
ひよこエンジニアtakei-hです。ぴよぴよ。
さて、amo-k先輩からの課題にやっと手を付けました!
さっそく本題です!
ども、amo-kです。
今回は、先日RIA的なアプリを作っていて遭遇した
問題について書きます。
IE × SSL × リソースDL
上記が重なった際に生じる問題です。
どうなるかといいますと、
HTTPレスポンスヘッダのキャッシュコントロール系で
意図した動作をしないという問題です。
例えば、
Pragma: no-cache
というレスポンスヘッダを定義していると
逆にcacheファイルを参照しようとするようです。
今回は、HTTPサーバ側でレスポンスの全てを構築していた訳ではありませんでした。
サーバサイドはphpアプリケーションでレスポンスヘッダ/メッセージボディを生成するのですが
phpはデフォルトでレスポンスヘッダを生成してくれます。
その際に
Pragma: no-cache
を入れてくれます。
これは嬉しいのですが、
上記IEのバグに対応するには、ヘッダを書き換える必要があります。
ということで以下のようにヘッダを上書きして対応しました。
header("Pragma: ");
一般的には、Webサイトの管理ツールなどで
SSL通信による集計ファイルのDLサービス等で
同様の現象が再現し得るでしょう。
JavaScriptじゃないんだし、
phpソースコード中にIEの対応を書くなんてと思いましたが
よくよく調べてみると、Microsoftサポートでも公開していたので
まあいっかと思った次第です。
takada-atです。
Rubyでソケットをいじっていたら、同じものをC/C++でも書いてみたくなりました。
そこで、C++でもHTTPクライアントに挑戦してみました。C/C++はよくわからないので、変なコードになっていると思いますが、遠慮なくつっこみをいただけるとうれしいです。
(そもそもコードが長すぎる気がします。。)
amo-kさんにつづき、私(takda-at)もHTTPクライアントを実装してみました。
まずはRubyのコードです。Rubyでは、socketというネットワークプログラミング用のライブラリが標準で用意されています。その中でもTCPSocketなどのクラスを利用するとHTTPクライアントなども非常に簡単につくれるのですが、今回は勉強のため、あえて低レイヤーなところから書いています。
socketライブラリの中でも、Socketクラスは、ソケットをシステムコールレベルで操作するための機能を提供しています。メソッド名などもシステムコールと同じ名前が採用されているようです。
Rubyリファレンスマニュアルの説明にはそこまで詳細な解説が無いので、LinuxなどのManPageも合わせて見た方が参考になります。
また今回は勉強のために、socketライブラリのソースコードも少しのぞいてみました。socketライブラリはC言語で書かれたRubyの拡張ライブラリです。最新の安定板であるRuby1.8.7では、ruby-1.8.7-p72/ext/socket/socket.c にソースコードがあります。
参考
-Socket - Rubyリファレンスマニュアル-
-Manpage of SOCKET
-Manpage of GETHOSTBYNAME
難しかったのはSocket::connectを呼び出し、接続を行なうところです。このメソッドの引数には、バイナリデータを文字列の形でわたします。C 言語のconnect関数には、引数として、sockaddr構造体というものをわたすのですが、Socket::conncetメソッドの場合、Rubyの側からCの構造体を文字列の形でわたしてやる必要があります。
Rubyで、データをバイナリ文字列に変換するにはArrayクラスのpackメソッドを利用します。
Rubyでバイナリデータを扱うプログラムを書いたのははじめてだったので、非常に勉強になりました。
参考
-Manpage of CONNECT
-Array::pack - Rubyリファレンスマニュアル
-packテンプレート文字列 - Rubyリファレンスマニュアル
Ruby でHTTP通信をする方法はいくつかあります。
最も簡単なのは、open-uriを使う方法でしょう。
単純にあるURIに対してGETリクエストを送り、返されたHTMLを表示するだけなら、以下のように1行で済ませることもできます。
$ ruby -ropen-uri -e 'open(ARGV[0]){|f| puts f.read }' http://www.klab.jp/
最初の投稿はSocketプログラミング!
最初のネタは、Socketプログラミングをしてみよう!というネタです。
通常、我々はライブラリやパッケージを使ってWebアプリケーションを実装します。
例えばアプリケーションから任意のHTTPリクエストするような処理を実装する際は、TCPクライアントの処理を意識せずにライブラリを呼び出すだけで実装できたりします。それでもいいっちゃいいのですが、あえて自前で実装してみようという試みです。
こうすることで、普段我々があまり意識していないTCP/IPの世界を意識するきっかけとなるのではと考えております。ということで、まずはSocket関数を用いてHTTPクライアントを書いてみることにします。
書いてみたきっかけ
PHPやRuby等で何気に使っているHTTPクライアント。
PHPだとfopen()やcURLでHTTPリクエストできたり、Rubyだとopen-uriのopen()等でHTTPリクエストができちゃいます。
ある日、自社Web API “FlaMixer” と連携する部分をPHPで書く機会があった。前述のfopen()やcURLのオプション指定だけでは連携が困難だったので、モジュールの使い方であれこれと悩むくらいなら自分で書いちゃえって事で書いてみました。これがきっかけでSocket関数を使ったコーディングを経験し、他の若手メンバにも経験してもらおう思いました。
ということで、言語はなんでもいいからHTTPクライアントを書いてみよう~
まずは言いだしっぺの若手amo-kのコード: