- PR -

C#でwebサーバーにPOSTでリクエストを投げても情報の取得がうまくいきません。

投稿者投稿内容
kitakita
会議室デビュー日: 2007/06/13
投稿数: 5
投稿日時: 2007-06-13 14:15
初めて投稿いたします。
長文で申し訳ありませんが、よろしくお願い致します。

C#でwebサーバーにPOSTでリクエストを投げて、情報を取得するアプリケーションを作成していますが情報の取得がうまくいきません。下記のようなプログラムでリクエストを投げると503エラーがでて失敗してしまいます。



public string postRequest(string url, string postData)
{
System.Text.Encoding enc =
System.Text.Encoding.GetEncoding("shift_jis");

byte[] postDataBytes = System.Text.Encoding.ASCII.GetBytes(postData);
//WebRequestの作成
System.Net.WebRequest req =
System.Net.WebRequest.Create(url);

//メソッドにPOSTを指定
req.Method = "POST";
//ContentTypeを"application/x-www-form-urlencoded"にする
req.ContentType = "application/x-www-form-urlencoded";
//POST送信するデータの長さを指定
req.ContentLength = postDataBytes.Length;

//データをPOST送信するためのStreamを取得
System.IO.Stream reqStream = req.GetRequestStream();
//送信するデータを書き込む
reqStream.Write(postDataBytes, 0, postDataBytes.Length);
reqStream.Close();

//サーバーからの応答を受信するためのWebResponseを取得
System.Net.WebResponse res = req.GetResponse();
//応答データを受信するためのStreamを取得
System.IO.Stream resStream = res.GetResponseStream();
//受信して表示
System.IO.StreamReader sr = new System.IO.StreamReader(resStream, enc);
string ret = sr.ReadToEnd();
//閉じる
sr.Close();

return ret;
}

サーバー側でパケットキャプチャしてみたところHTTP/1.1 100 Continueのあとでリクエストの本文が送信されていないようです。

POST /viewer/channelrenewal HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 22
Expect: 100-continue
Host: xxx.xxx.xxx.xxx
X-Client-For: xxx.xxx.xxx.xxx
Connection: close
X-BlueCoat-Via: xxxxxxxxxxxxxxx

HTTP/1.1 100 Continue

■環境
[ クライアント ]
WindowsXP SP1

[ サーバ ]
RedHat8.0
Apache1.3

どうしてPOSTがうまくいかないのかご教授願えますでしょうか?
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-06-13 14:35
引用:
サーバー側でパケットキャプチャしてみたところHTTP/1.1 100 Continueのあとでリクエストの本文が送信されていないようです。

これってサーバが「続けてどうぞ」っていってるんですよね?
続けてリクエストするコードを書いてないからうまくいかないんじゃないですか?

htmlでformを書いて試したらうまくいきますか?
rvmx
大ベテラン
会議室デビュー日: 2002/09/26
投稿数: 184
お住まい・勤務地: 愛媛県
投稿日時: 2007-06-13 17:41
今日は

私が普通に使っている方法は
reqStream.Writeの後に直ぐにはreqStream.Close()で閉じないで、
通信が完了するまで保持しています。
又、System.IO.StreamReader sr = new System.IO.StreamReader(resStream, enc);
もSystem.IO.StreamReader sr = new System.IO.StreamReader(resStream.GetRequestStrem(), enc);を使っています。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-06-13 19:21
引用:
続けてリクエストするコードを書いてないからうまくいかないんじゃないですか?

いや、そうじゃないかもしれない。。

100 Continue でとまってるってことは、503エラーっていうのはapacheじゃなくてASP.NET側が
出してるってことですよね?とりあえずエラーをcatchして中身みてみればいいんじゃないですか?
試した感じだと、そのコードでPOSTしてレスポンスを受け取ること自体はできています。

#HttpWebRequestならContinueDelegateなんていうプロパティがあるみたいです。

[追記]ぁ、私はC#側がASP.NETだと勝手に思い込んで書いてました。Winアプリとかカも知れませんね。。

[ メッセージ編集済み 編集者: べる 編集日時 2007-06-13 23:32 ]
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-13 19:58
引用:

べるさんの書き込み (2007-06-13 19:21) より:
引用:
続けてリクエストするコードを書いてないからうまくいかないんじゃないですか?

いや、そうじゃないかもしれない。。

100 Continue でとまってるってことは、503エラーっていうのはapacheじゃなくてASP.NET側が
出してるってことですよね?



WebExceptionのStatusがProtocolErrorになっている場合は
HTTPレベルのエラーですのでASP.NETとかは関係ないです。

HTTPの503エラーはService Unavailableですので、
普通はサーバーが停止中を意味しますが、あまり当てになりません。
500番台はセキュリティとかサーバーの実装とか、
いろんな事情が絡みますので、額面どおり受け取れません。

100Continueは帰ってきてるので、
リクエストラインとヘッダーの送信はうまくいっています。

コードを見ましたが、
私にはメッセージボディが送信されない理由がわかりませんでした。
ただ、ひとつ気になる点があります。
キャプチャのログです。

引用:

X-Client-For: xxx.xxx.xxx.xxx
Connection: close
X-BlueCoat-Via: xxxxxxxxxxxxxxx



これはなんでしょう?
そのコードでは普通上記のようなヘッダは送られないはずです。
間にプロキシなどが入っているのですか?

HTTP1.0プロキシが入っていると、先ほどのコードではうまくいかないはずです。
HTTP1.1プロキシならうまくいくと思うのですが。

動作環境をもう一度確認してみてください。


[ メッセージ編集済み 編集者: れい 編集日時 2007-06-13 19:59 ]
kitakita
会議室デビュー日: 2007/06/13
投稿数: 5
投稿日時: 2007-06-13 20:00
べるさん、rvmxさん、早速のご返信ありがとうございます。
htmlのformでPOSTするとうまく動作します。
reqStream.Close()を閉じないで

System.IO.StreamReader sr = new System.IO.StreamReader(resStream.GetRequestStrem(), enc);

という形に変更して試してみましたが矢張り同様の現象が起こりました。
htmlからのPOSTした場合とC#で作成したアプリからアクセスした場合の、キャプチャの差分を調べたところブラウザからだと、

Expect: 100-continue

というヘッダーを送っていないようです。そこで

((System.Net.HttpWebRequest)req).Expect = null;

として送ってみましたがヘッダー内容をキャプチャしますと「Expect: 100-continue」がついたままとなっています。
HttpWebRequestじゃなくてWebClientを使えば設定できるという記載を見かけたので試してみましたが駄目でした。

プロキシサーバを経由しないようにするとうまく接続できるので、プロキシサーバで「HTTP/1.1 100 Continue」が返って来た場合、うまく処理できないのかもしれません。javaでも同様のソースを書いてみてプロキシサーバ経由で「Expect: 100-continue」ヘッダーをつけた場合とつけていない場合を試したところヘッダーをつけるとやはり同様の現象が起こりました。
ただ、作成しているアプリケーションはプロキシ越しのアクセスも許可する仕様となっているため、プロキシサーバを経由しないようにする訳にはいきません。
C#でのHTTPヘッダーの設定の仕方を調べていろいろと試してみていますが今のところうまくいっていません。

ContinueDelegateについても調べて見ます。ありがとうございます。
kitakita
会議室デビュー日: 2007/06/13
投稿数: 5
投稿日時: 2007-06-13 20:15
引用:

引用:

X-Client-For: xxx.xxx.xxx.xxx
Connection: close
X-BlueCoat-Via: xxxxxxxxxxxxxxx



これはなんでしょう?
そのコードでは普通上記のようなヘッダは送られないはずです。
間にプロキシなどが入っているのですか?

HTTP1.0プロキシが入っていると、先ほどのコードではうまくいかないはずです。
HTTP1.1プロキシならうまくいくと思うのですが。

動作環境をもう一度確認してみてください。




れいさんご返信ありがとうございます。
こちらのログはIPなどが入っていたため敢えて伏字にして投稿いたしました。
説明不足で申し訳ありません。

先ほどの返信にも書きましたがどうもプロキシサーバを経由すると動作しないので、Expectヘッダーを送らないように設定しようとしていますがうまく設定できていません。

ご指摘いただきました動作環境も調べて見ます。ありがとうございます。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-13 20:15
引用:

ただ、作成しているアプリケーションはプロキシ越しのアクセスも許可する仕様となっているため、プロキシサーバを経由しないようにする訳にはいきません。



やはりプロキシ越しだったのですね。

詳細は省きますが、
Expect: 100-Continueを送らないようにするといろいろ問題が起こります。

ただしいHTTP1.1プロキシを用いるのがいいと思いますが、
どうしてもExpectヘッダーを除きたい場合は
以下のコードを関数の最初で呼べばいけます。

コード:

ServicePointManager.FindServicePoint( url ).Expect100Continue = false;



いろいろ問題が発生します。
覚悟の上でどうぞ。



[ メッセージ編集済み 編集者: れい 編集日時 2007-06-13 20:22 ]

スキルアップ/キャリアアップ(JOB@IT)