01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
2009-08-13 Thu
■ HTTP クライアントを書いた [D言語]
HTTP/0.9 用のクライアントを書いた。
サイトによってはレスポンスヘッダが帰ってくる。
次は、1.0を実装してみよう。
private import std.socket; private import std.string; private import std.regex; private import std.conv; struct URI { string scheme; string host; string port; string path; string query; string fragment; this(string uri) { auto r = regex(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?","g"); foreach (m; match(uri, r)) { if(m.pmatch[2].startIdx != -1) scheme = m.input[m.pmatch[2].startIdx .. m.pmatch[2].endIdx]; if(m.pmatch[4].startIdx != -1) { int len = m.input[m.pmatch[4].startIdx .. m.pmatch[4].endIdx].indexOf(":"); if(len != -1) { host = m.input[m.pmatch[4].startIdx .. m.pmatch[4].startIdx + len]; port = m.input[m.pmatch[4].startIdx + len + 1 .. m.pmatch[4].endIdx]; }else{ host = m.input[m.pmatch[4].startIdx .. m.pmatch[4].endIdx]; } } if(m.pmatch[5].startIdx != -1) path = m.input[m.pmatch[5].startIdx .. m.pmatch[5].endIdx]; if(m.pmatch[7].startIdx != -1) query = m.input[m.pmatch[7].startIdx .. m.pmatch[7].endIdx]; if(m.pmatch[9].startIdx != -1) fragment = m.input[m.pmatch[9].startIdx .. m.pmatch[9].endIdx]; } } const string toString() { string s; if(scheme) s ~= scheme ~ ":"; if(host) s ~= "//" ~ host; if(port) s ~= ":" ~ port; if(path) { s ~= path; }else{ s ~= "/"; } if(query) s ~= "?" ~ query; if(fragment) s ~= "#" ~ fragment; return s; } } class HttpClient { private: TcpSocket socket; string httpVersion; public: this(string httpVersion) { switch(httpVersion) { case "HTTP/0.9": this.httpVersion = httpVersion; break; default: new Exception("HTTPVersion not supported"); } } byte[] get(in string uri) { switch(httpVersion) { case "HTTP/0.9": URI u = URI(uri); ushort port = 80; if(u.port) port = to!(ushort)(u.port); auto ia = new InternetAddress(u.host,port); socket = new TcpSocket(ia); string req = "GET " ~ u.path ~ "\r\n"; socket.send(req); int read; byte[] recv; byte[1024] buf; while((read = socket.receive(buf)) > 0) { recv ~= buf[0 .. read]; } return recv; default: new Exception("HTTPVersion not supported"); } } byte[] get(in string uri,in string proxy) { switch(httpVersion) { case "HTTP/0.9": URI u = URI(uri); URI p = URI(proxy); if(p.port) port = to!(ushort)(p.port); auto ia = new InternetAddress(p.host,port); socket = new TcpSocket(ia); string req = "GET " ~ u.toString ~ "\r\n"; int sent; sent = socket.send(req); if(sent == -1) { throw new Exception("error socket send"); } int read; byte[] recv; byte[1024] buf; while((read = socket.receive(buf)) > 0) { recv ~= buf[0 .. read]; } if(read == -1) { throw new Exception("error socket recive"); } return recv; default: new Exception("HTTPVersion not supported"); } } }
使い方
auto client = new HttpClient("HTTP/0.9"); byte[] recv = client.get("http://example.com/"); write(cast(char[])recv);