서버에서 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);
}
답변
흥미롭게도 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 인코딩 된 데이터 조각 사이에 끝을 두는 것입니다. 내가 꺼내면 모든 것이 효과가있었습니다. 유사한 기술을 사용하여 서비스에 연결하고 실제 응답 오류 텍스트를 읽을 수 있습니다.
답변
이것을 시도하십시오 (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 개의 컨텐츠를 “잘못된 요청”으로 변경합니다.
솔루션 : 이 문제 를 해결하기 위해
추가 ; 이제 모든 서버 (로컬 및 원격)는 내가 반환하는 IP 주소 및 / 또는 HTTP 코드에 관계없이 정확히 동일한 내용 (내가 생성 한)을 반환합니다.<httpErrors existingResponse="PassThrough"></httpErrors>
web.config/configuration/system.webServer