I'm implementing a Proxy for my application using ASP.NET WebApi (ApiController) and using HttpClient to make the request with my authorization header. It works fine, but it's extremely slow. Below is the main code, then the Global initialization (with DefaultConnectionLimit) and web.config related piece.
As you can see, I'm already using a static/shared HttpClient object with no Proxy and HttpCompletionOption.ResponseHeadersRead on the actual request. This WebApi endpoint is called in parallel, which works fine.
The entire code runs fast enough, but as I'm using ResponseHeadersRead async, the HttpRequestMessage is returned and the rest of the body is downloaded and streamed directly to the client/caller.
Here is a video showing the problem.
public class ProxyController : ApiController
{
private const string BASE_URL = "https://developer.api.autodesk.com";
private const string PROXY_ROUTE = "api/viewerproxy/";
// HttpClient has been designed to be re-used for multiple calls. Even across multiple threads.
// https://stackoverflow.com/questions/22560971/what-is-the-overhead-of-creating-a-new-httpclient-per-call-in-a-webapi-client
private static HttpClient _httpClient;
[HttpGet]
[Route(PROXY_ROUTE + "{*.}")]
public async Task<HttpResponseMessage> Get()
{
if (_httpClient == null)
{
_httpClient = new HttpClient(new HttpClientHandler()
{
UseProxy = false,
Proxy = null
});
_httpClient.BaseAddress = new Uri(BASE_URL);
}
string url = Request.RequestUri.AbsolutePath.Replace(PROXY_ROUTE, string.Empty);
string absoluteUrl = url + Request.RequestUri.Query;
try
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, absoluteUrl);
request.Headers.Add("Authorization", "Bearer " + AccessToken);
HttpResponseMessage response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
return response;
}
catch (Exception e)
{
return new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
}
}
}
Global.asax, although I don't believe is a problem of connection limit as all the requests are processed, but just too slow...
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(Config.WebApiConfig.Register);
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = false;
ServicePointManager.CheckCertificateRevocationList = true;
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
}
}
And part of the Web.Config
<system.web>
<compilation debug="true" targetFramework="4.6" />
<httpRuntime targetFramework="4.6" maxRequestLength="2097151" requestLengthDiskThreshold="16384" requestPathInvalidCharacters="<,>,*,%,&,\,?" />
</system.web>
Solved by removing the
<system.diagnostics>
section of the web.config. It seems that it was causing an excess of output and slowing down allHttpClient
requests.For the record, this the code I was using and causing the slowness on all
HttpClient.SendAsync
calls. But this is useful for tracking connection problems :-)