我有一个C#应用程序,它充当外部REST API的伪HTTP代理。我正在使用System.Net.HttpListener
侦听请求,并使用System.Net.Http.HttpClient
向上游转发请求。一旦我收到回复,我就会发回给原始请求者(客户端)。如果我在执行此操作时遇到异常,则会向客户端返回400状态代码,并返回一个包含exception.ToString()
的简单网页。它天真地假设,如果它无法到达要求的位置,那就是客户端的错,因为URL很糟糕等等。
这基本上就是我正在做的事情:
private async Task ProcessRequestAsync(HttpListenerContext context)
{
try {
HttpRequestMessage requestMessage = new HttpRequestMessage();
//Some code to set up the requestMessage
HttpResponseMessage responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false);
//Some code to set up the context.Response
using (Stream s = context.Response.OutputStream) {
byte[] replyContent = await responseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
s.Write(replyContent, 0, replyContent.Length);
}
} catch (Exception e) {
try {
Trace.TraceWarning("Unable to handle request.\r\n{0}", e.ToString());
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.Response.StatusDescription = "Bad Request";
context.Request.Headers.Clear();
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.ContentType = "text/html";
context.Response.ProtocolVersion = context.Request.ProtocolVersion;
context.Response.KeepAlive = false;
context.Response.SendChunked = false;
using (Stream s = context.Response.OutputStream) {
byte[] content = Encoding.UTF8.GetBytes(
"<!DOCTYPE html>\r\n" +
"<html lang=\"en\">\r\n" +
" <head>\r\n" +
" <meta content=\"text/html; charset=utf-8\" http-equiv=\"Content-Type\" />\r\n" +
" <title>Error</title>\r\n" +
" </head>\r\n" +
" <body>\r\n" +
" <h1>Error: Unable to handle request.</h1>\r\n" +
" <pre>" + e.ToString().Replace("&", "&")
.Replace("<", "<")
.Replace(">", ">") + "</pre>\r\n" +
" </body>\r\n" +
"</html>\r\n");
context.Response.ContentLength64 = content.Length;
s.Write(content, 0, content.Length);
}
} catch (Exception f) {
Trace.TraceError("Could not send response back to requester.\r\n{0}", f.ToString());
}
}
}
问题是有时502(坏网关)状态将引发异常并导致客户端接收HTTP状态代码400,但有时它不会,客户端获取正确的502状态代码。如果我得到一个,我想总是返回正确的HTTP状态代码。
以下是例外:
System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.WebException: The remote server returned an error: (502) Bad Gateway.
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Runner.Runner.<ProcessRequestAsync>d__9.MoveNext()
编辑:
以下是调用ProcessRequestAsync
的代码。 server
是我的HttpListener
的名称,此代码作为Windows服务运行。
public void Start()
{
server.Start();
Task.Run(async () => {
while (true)
try {
var context = await server.GetContextAsync();
// I'm using Task.Run here without await so I can
// immediately listen for another request
Task.Run(() => ProcessRequestAsync(context));
} catch (HttpListenerException) {
break; // Listener stopped.
} catch (InvalidOperationException) {
break; // Listener stopped.
}
});
}