Skip to content

Commit ad2beaf

Browse files
committed
Delegating handler for Http redirects
1 parent be65955 commit ad2beaf

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using GitHub.Runner.Sdk;
8+
using GitHub.Services.Common;
9+
10+
namespace GitHub.Runner.Common
11+
{
12+
/// <summary>
13+
/// Handles redirects for Http requests
14+
/// </summary>
15+
[EditorBrowsable(EditorBrowsableState.Never)]
16+
public class RedirectMessageHandler : DelegatingHandler
17+
{
18+
public RedirectMessageHandler(ITraceWriter trace)
19+
{
20+
Trace = trace;
21+
}
22+
23+
protected override async Task<HttpResponseMessage> SendAsync(
24+
HttpRequestMessage request,
25+
CancellationToken cancellationToken)
26+
{
27+
HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
28+
29+
if (response != null &&
30+
IsRedirect(response.StatusCode) &&
31+
response.Headers.Location != null)
32+
{
33+
Trace.Info($"Redirecting to '{response.Headers.Location}'.");
34+
35+
request = await CloneAsync(request, response.Headers.Location).ConfigureAwait(false);
36+
37+
response.Dispose();
38+
39+
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
40+
}
41+
42+
return response;
43+
}
44+
45+
private static bool IsRedirect(HttpStatusCode statusCode)
46+
{
47+
return (int)statusCode >= 300 && (int)statusCode < 400;
48+
}
49+
50+
private static async Task<HttpRequestMessage> CloneAsync(HttpRequestMessage request, Uri requestUri)
51+
{
52+
var clone = new HttpRequestMessage(request.Method, requestUri)
53+
{
54+
Version = request.Version
55+
};
56+
57+
request.Headers.ForEach(header => clone.Headers.TryAddWithoutValidation(header.Key, header.Value));
58+
59+
request.Options.ForEach(option => clone.Options.Set(new HttpRequestOptionsKey<object>(option.Key), option.Value));
60+
61+
if (request.Content != null)
62+
{
63+
clone.Content = new ByteArrayContent(await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false));
64+
65+
request.Content.Headers.ForEach(header => clone.Content.Headers.TryAddWithoutValidation(header.Key, header.Value));
66+
}
67+
68+
return clone;
69+
}
70+
71+
private readonly ITraceWriter Trace;
72+
}
73+
}

src/Runner.Worker/JobRunner.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,14 @@ public async Task<TaskResult> RunAsync(AgentJobRequestMessage message, Cancellat
8484
Trace.Info($"Creating job server with URL: {jobServerUrl}");
8585
// jobServerQueue is the throttling reporter.
8686
_jobServerQueue = HostContext.GetService<IJobServerQueue>();
87-
VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential, new DelegatingHandler[] { new ThrottlingReportHandler(_jobServerQueue) });
87+
var delegatingHandlers = new List<DelegatingHandler>() { new ThrottlingReportHandler(_jobServerQueue) };
88+
message.Variables.TryGetValue("system.github.enable_http_redirects", out VariableValue enableHttpRedirects);
89+
if (StringUtil.ConvertToBoolean(enableHttpRedirects?.Value) &&
90+
!StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_NO_HTTP_REDIRECTS")))
91+
{
92+
delegatingHandlers.Add(new RedirectMessageHandler(Trace));
93+
}
94+
VssConnection jobConnection = VssUtil.CreateConnection(jobServerUrl, jobServerCredential, delegatingHandlers);
8895
await jobServer.ConnectAsync(jobConnection);
8996

9097
_jobServerQueue.Start(message);

0 commit comments

Comments
 (0)