私はサーバーからHTTP 400コードを取得したときに、サーバーがリクエストの何が問題であったかを(HTTP応答コンテンツのメッセージを使用して)通知する完全に合法的な状況にあります
ただし、ステータスコードが400の場合、.NET HttpWebRequestは例外を発生させます。
これをどのように処理しますか?私にとって、400は完全に合法であり、かなり役に立ちます。HTTPコンテンツにはいくつかの重要な情報が含まれていますが、例外が原因で私のパスから外れてしまいます。
私はサーバーからHTTP 400コードを取得したときに、サーバーがリクエストの何が問題であったかを(HTTP応答コンテンツのメッセージを使用して)通知する完全に合法的な状況にあります
ただし、ステータスコードが400の場合、.NET HttpWebRequestは例外を発生させます。
これをどのように処理しますか?私にとって、400は完全に合法であり、かなり役に立ちます。HTTPコンテンツにはいくつかの重要な情報が含まれていますが、例外が原因で私のパスから外れてしまいます。
回答:
「成功しないコードでスロー」をオフにする方法があったらいいのですが、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);
}
WebException.Response
することができますnull
。この場合は、再スローする必要があります。
HttpClient
代わりに使用する必要があります。もっと構成しやすく、将来の道だと思います。
((WebRequest) null).GetResponseWithoutException()
実際にはは発生しません。NullReferenceException
これはと同等にコンパイルされるため、WebRequestExtensions.GetResponseWithoutException(null)
結果としてが発生しないため、NullReferenceException
入力の検証が必要になります。
興味深いことに、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エンコードされたデータの間にエンドラインを挿入していたことでした。私がそれらを取り出したとき、すべてがうまくいきました。同様の手法を使用してサービスに接続し、実際の応答エラーテキストを読み取ることができる場合があります。
これは私のためにそれを解決しました:https:
//gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL; DR:
問題:
localhostのリターンが期待コンテンツ、リモートIP変更「不正な要求」に400コンテンツ
ソリューション:
追加する<httpErrors existingResponse="PassThrough"></httpErrors>
にはweb.config/configuration/system.webServer
私のためにこれを解決しました。現在、すべてのサーバー(ローカルとリモート)は、返すIPアドレスやHTTPコードに関係なく、まったく同じコンテンツ(私が生成したもの)を返します。