例えば以下の様なアドレスでGET要求を送信します
http://www.google.com/reader/atom/feed/http://blog.atelierlune.com/atom.xml?xt=user/-/state/com.google/read
これが、.NETのHttpWebRequestを使って処理すると、内部処理でリクエストアドレスに含まれる"//"が"/"となってしまいます。コレは相対アドレスを絶対アドレスに変換しようとしてるのかも知れませんが、Googleのサーバへの要求としては不適切となってしまいます
この問題がどうしても解決する方法がわからないので、Http Requestを自前で処理するようにしてみました。
なんだか無駄な事をしている様に思います
本来ならサーバーからxmlデータを取得するだけなら
XmlDocument.Load(url);
を使用するだけで済みます。
今回はGoogleへのユーザー認証済みのCookie付きでアクセスするために、HttpWebRequestを使ってきましたが、更にHttp Requestまで自前で書くことに....
とりあえず目的のFeed情報は取得できるようになったけど、
自前で記述したHttpRequestはSSL通信は無理だろうなぁ...
とりあえず試験的に書いたソース。どっかの解説ページそのまんま+Chunked Encodingの解除
TcpClientクラスを使うともう少しスッキリ書けるのかな?
public String HttpGet(String url,String param)
{
url = url.Substring(url.IndexOf("://")+3);
String server = url.Substring(0,url.IndexOf("/"));
url = url.Substring(server.Length);
IPAddress hostaddr = Dns.GetHostByName(server).AddressList[0];
IPEndPoint hostendp = new IPEndPoint(hostaddr,80);
String reqMsg = "GET " + url + " HTTP/1.1\r\n"
+ "HOST: " + server + "\r\n"
+ "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9\r\n"
+ "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
+ "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n"
+ "Accept-Charset: utf-8;q=0.7,*;q=0.7\r\n";
if (param != null)
reqMsg += param + "\r\n";
reqMsg += "Connection: Close\r\n\r\n";
byte []reqBytes = Encoding.UTF8.GetBytes(reqMsg);
System.Net.Sockets.Socket sock = new System.Net.Sockets.Socket(
System.Net.Sockets.AddressFamily.InterNetwork,
System.Net.Sockets.SocketType.Stream,
System.Net.Sockets.ProtocolType.Tcp);
sock.Connect(hostendp);
sock.Send(reqBytes,reqBytes.Length,System.Net.Sockets.SocketFlags.None);
byte [] resByte=new byte[1024];
System.IO.MemoryStream mem = new MemoryStream();
// 受信
while (true)
{
int rsize = sock.Receive(resByte, resByte.Length, System.Net.Sockets.SocketFlags.None);
if (rsize == 0)
break;
mem.Write(resByte, 0, rsize);
}
mem.Seek(0, SeekOrigin.Begin);
// ヘッダの解釈
String [] resHdr = ReadLine(mem).Split(' ');
if (!resHdr[0].StartsWith("HTTP/")
|| !resHdr[1].StartsWith("200"))
{
throw new ArgumentException("Http Response Error");
}
// ヘッダの終わりまで読み飛ばす
bool Chunked=false;
while(true)
{
String hdr = ReadLine(mem);
if(hdr.StartsWith("Transfer-Encoding:"))
{
if(hdr.Substring("Transfer-Encoding:".Length).Trim().ToLower() =="chunked")
Chunked=true;
}
else if(hdr=="")
break;
}
// 本文を取得する(Chunkedの場合)
string resMsg="";
if(Chunked)
{
while (true)
{
String lens = ReadLine(mem).TrimEnd(';');
int len = 0;
if (lens != "")
len = Int32.Parse(lens, System.Globalization.NumberStyles.AllowHexSpecifier);
if (len == 0)
break;
resMsg += Encoding.UTF8.GetString(mem.GetBuffer(), (int)mem.Position, len);
mem.Seek(len, SeekOrigin.Current);
// 改行を捨てる
ReadLine(mem);
}
}
else
{
resMsg = Encoding.UTF8.GetString(mem.GetBuffer(), (int)mem.Position, (int)mem.Length);
}
mem.Close();
//閉じる
sock.Shutdown(System.Net.Sockets.SocketShutdown.Both);
sock.Close();
return resMsg;
}
2 件のコメント:
おもいっきりはずしている可能性が高いですが,
http://www.google.com/reader/atom/feed/http%3A%2F%2Fblog.atelierlune.c
みたいにURLエンコードしても駄目ですか?
oriさんコメントありがとうございます
ためしに
Uri uri = new Uri("http://www.google.com/reader/atom/feed/http%3A%2F%2Fblog.atelierlune");
ってやってみると、
http://www.google.com/reader/atom/feed/http%3A/blog.atelierlune
となったので、だめみたいです...
今はTcpClientを使ってプログラムを書き直しているのですが、なぜか送信文字列にゴミが入ってしまって通信エラーになってしまいます
なかなか思うようには行かないです
コメントを投稿