I have a C # application that acts as an HTTP pseudo-proxy server for an external REST API. I listen to requests using System.Net.HttpListener and forward them upstream using System.Net.Http.HttpClient . As soon as I receive a response, I send it back to the original requestor (client). If I get an exception while doing this, I return a 400 status code to the client and a simple web page with exception.ToString() . He naively believes that if he could not get where he was asked to go, this is a client error, because the URL is bad, etc.
This is basically all I do:
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()); } } }
The problem is that sometimes the status 502 (Bad Gateway) throws an exception and forces the client to receive the HTTP status code 400, but sometimes it is not, and the client receives the correct status code 502. I would like to always return the correct HTTP status code if I receive his.
Here's the exception:
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()
EDIT:
Below is the code that calls ProcessRequestAsync . server is the name of my HttpListener , and this code works like a windows service.
public void Start() { server.Start(); Task.Run(async () => { while (true) try { var context = await server.GetContextAsync();
source share