Skip to content

Commit

Permalink
First attempt to reuse HttpClient
Browse files Browse the repository at this point in the history
  • Loading branch information
darrelmiller committed May 13, 2015
1 parent bef91f7 commit e5d7d6e
Showing 1 changed file with 97 additions and 19 deletions.
116 changes: 97 additions & 19 deletions Octokit/Http/HttpClientAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ namespace Octokit.Internal
public class HttpClientAdapter : IHttpClient
{
readonly IWebProxy _webProxy;

HttpClient _http;

public HttpClientAdapter() { }

public HttpClientAdapter(IWebProxy webProxy)
public HttpClientAdapter(IWebProxy webProxy, HttpMessageHandler handler = null)
{
_webProxy = webProxy;

if (handler == null)
{
handler = GetHandler();
}

_http = new HttpClient(new RedirectHandler() { InnerHandler = handler});

}

/// <summary>
Expand All @@ -36,21 +45,20 @@ public async Task<IResponse> Send(IRequest request, CancellationToken cancellati
{
Ensure.ArgumentNotNull(request, "request");

var httpOptions = new HttpClientHandler
{
AllowAutoRedirect = request.AllowAutoRedirect
};
if (httpOptions.SupportsAutomaticDecompression)
{
httpOptions.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
if (httpOptions.SupportsProxy && _webProxy != null)

var cancellationTokenForRequest = GetCancellationTokenForRequest(request, cancellationToken);

using (var requestMessage = BuildRequestMessage(request))
{
httpOptions.UseProxy = true;
httpOptions.Proxy = _webProxy;
// Make the request
var responseMessage = await _http.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, cancellationTokenForRequest)
.ConfigureAwait(false);
return await BuildResponse(responseMessage).ConfigureAwait(false);
}
}

var http = new HttpClient(httpOptions);
static CancellationToken GetCancellationTokenForRequest(IRequest request, CancellationToken cancellationToken)
{
var cancellationTokenForRequest = cancellationToken;

if (request.Timeout != TimeSpan.Zero)
Expand All @@ -60,14 +68,26 @@ public async Task<IResponse> Send(IRequest request, CancellationToken cancellati

cancellationTokenForRequest = unifiedCancellationToken.Token;
}
return cancellationTokenForRequest;
}

using (var requestMessage = BuildRequestMessage(request))

private HttpClientHandler GetHandler()
{
var httpOptions = new HttpClientHandler
{
// Make the request
var responseMessage = await http.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, cancellationTokenForRequest)
.ConfigureAwait(false);
return await BuildResponse(responseMessage).ConfigureAwait(false);
AllowAutoRedirect = false
};
if (httpOptions.SupportsAutomaticDecompression)
{
httpOptions.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
if (httpOptions.SupportsProxy && _webProxy != null)
{
httpOptions.UseProxy = true;
httpOptions.Proxy = _webProxy;
}
return httpOptions;
}

protected async virtual Task<IResponse> BuildResponse(HttpResponseMessage responseMessage)
Expand Down Expand Up @@ -109,6 +129,8 @@ protected virtual HttpRequestMessage BuildRequestMessage(IRequest request)
{
var fullUri = new Uri(request.BaseAddress, request.Endpoint);
requestMessage = new HttpRequestMessage(request.Method, fullUri);

requestMessage.Properties["AllowAutoRedirect"] = request.AllowAutoRedirect;
foreach (var header in request.Headers)
{
requestMessage.Headers.Add(header.Key, header.Value);
Expand Down Expand Up @@ -153,4 +175,60 @@ static string GetContentMediaType(HttpContent httpContent)
return null;
}
}

public class RedirectHandler : DelegatingHandler
{
public bool Enabled { get; set; }

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{

var response = await base.SendAsync(request, cancellationToken);

var allowAutoRedirect = (bool)request.Properties["AllowAutoRedirect"];
if (!allowAutoRedirect) return response;

if (response.StatusCode == HttpStatusCode.MovedPermanently
|| response.StatusCode == HttpStatusCode.Moved
|| response.StatusCode == HttpStatusCode.Redirect
|| response.StatusCode == HttpStatusCode.Found
|| response.StatusCode == HttpStatusCode.SeeOther
|| response.StatusCode == HttpStatusCode.RedirectKeepVerb
|| response.StatusCode == HttpStatusCode.TemporaryRedirect
|| (int)response.StatusCode == 308)
{

var newRequest = CopyRequest(response.RequestMessage);

if (response.StatusCode == HttpStatusCode.Redirect
|| response.StatusCode == HttpStatusCode.Found
|| response.StatusCode == HttpStatusCode.SeeOther)
{
newRequest.Content = null;
newRequest.Method = HttpMethod.Get;
}
newRequest.RequestUri = response.Headers.Location;

response = await base.SendAsync(newRequest, cancellationToken);
}

return response;
}

private static HttpRequestMessage CopyRequest(HttpRequestMessage oldRequest)
{
var newrequest = new HttpRequestMessage(oldRequest.Method, oldRequest.RequestUri);

foreach (var header in oldRequest.Headers)
{
newrequest.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
foreach (var property in oldRequest.Properties)
{
newrequest.Properties.Add(property);
}
if (oldRequest.Content != null) newrequest.Content = new StreamContent(oldRequest.Content.ReadAsStreamAsync().Result);
return newrequest;
}
}
}

0 comments on commit e5d7d6e

Please sign in to comment.