.純HttpWebRequest.GetResponse()を例外がレスポンスのhttpステータスコード400(bad request)が返される
-
22-08-2019 - |
質問
私が時を取得しますHTTP400コードをサーバからは完全に合法的な方法でサーバを聞かせていただきまして何が間違っていた自分の要求を使用してメッセージをHTTPレスポンスを返す動作のコンテンツ)
します。純HttpWebRequest上げる場合の例外のステータスコード400.
う扱うか。私にとって400は完全に合法ると、割としっかりとした。HTTPのコンテンツの一部の重要な情報が、例外はスローだと私のパスです。
解決
うにコミュニケーションを取り合があったものをoff"スロー以外の成功にコード"がキャッチしてください。WebExceptionできる少なくとも使用に対応:
using System;
using System.IO;
using System.Web;
using System.Net;
public class Test
{
static void Main()
{
WebRequest request = WebRequest.Create("http://csharpindepth.com/asd");
try
{
using (WebResponse response = request.GetResponse())
{
Console.WriteLine("Won't get here");
}
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse) response;
Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
}
}
}
するのがいいと思いますの封止に"く対応してもいない場合は、成功をコード"のビットは別の方法です。(めることをお勧めしたいものを投げればというものはありませんの対応などませんでしたが、少し足を延ばせば明します。)
の場合はエラー応答が大きくなる珍しいものとします。た調節のために HttpWebRequest.DefaultMaximumErrorResponseLength
うに全体のエラーになります。
他のヒント
これはかなり前にすでに回答されているとは思いますが、この質問に来た他の人を助けるために拡張メソッドを作成しました。
コード:
public static class WebRequestExtensions
{
public static WebResponse GetResponseWithoutException(this WebRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
try
{
return request.GetResponse();
}
catch (WebException e)
{
if (e.Response == null)
{
throw;
}
return e.Response;
}
}
}
使用法:
var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com");
//... (initialize more fields)
using (var response = (HttpWebResponse)request.GetResponseWithoutException())
{
Console.WriteLine("I got Http Status Code: {0}", response.StatusCode);
}
興味深いことに、 HttpWebResponse.GetResponseStream()
から得られるもの WebException.Response
サーバーから受信する応答ストリームと同じではありません。私たちの環境では、次の場合に実際のサーバー応答が失われます。 400 HTTP ステータス コードは、を使用してクライアントに返されます。 HttpWebRequest/HttpWebResponse
オブジェクト。これまで見てきたことから、応答ストリームは WebException's HttpWebResponse
はクライアントで生成され、サーバーからの応答本文は含まれません。不正なリクエストの理由をクライアントにメッセージで返したいので、非常にイライラします。
GoogleののOAuth2サービスに接続しようとしたとき、私は同様の問題がありました。
私はこのように、WebRequestクラスを使用していない、手動でPOSTを書いてしまいました
TcpClient client = new TcpClient("accounts.google.com", 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient("accounts.google.com");
{
byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString());
StringBuilder msg = new StringBuilder();
msg.AppendLine("POST /o/oauth2/token HTTP/1.1");
msg.AppendLine("Host: accounts.google.com");
msg.AppendLine("Content-Type: application/x-www-form-urlencoded");
msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString());
msg.AppendLine("");
Debug.WriteLine("Request");
Debug.WriteLine(msg.ToString());
Debug.WriteLine(content.ToString());
byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
sslStream.Write(headerAsBytes);
sslStream.Write(contentAsBytes);
}
Debug.WriteLine("Response");
StreamReader reader = new StreamReader(sslStream);
while (true)
{ // Print the response line by line to the debug stream for inspection.
string line = reader.ReadLine();
if (line == null) break;
Debug.WriteLine(line);
}
応答ストリームに書き込まれます応答はあなたが後にしている特定のエラーテキストが含まれています。
具体的には、私の問題は、私は、URLエンコードされたデータ片の間endlinesを入れていたということでした。私はそれらを取ったとき、すべてが働きました。あなたは、あなたのサービスに接続し、実際の応答エラーテキストを読むために同様の技術を使用することができるかもしれません。
(それはVB-コードです: - ):これを試してみてください。
Try
Catch exp As WebException
Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
拡張機能の非同期バージョン:
public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
{
try
{
return await request.GetResponseAsync();
}
catch(WebException ex)
{
return ex.Response;
}
}
これで私にとっては解決しました:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL;DR:
問題:
localhost が予期したコンテンツを返し、リモート IP が 400 コンテンツを「Bad Request」に変更します
解決:
追加 <httpErrors existingResponse="PassThrough"></httpErrors>
に web.config/configuration/system.webServer
私にとってはこれで解決しました。これで、私が返す IP アドレスや HTTP コードに関係なく、すべてのサーバー (ローカルおよびリモート) がまったく同じコンテンツ (私が生成した) を返します。