Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SystemWebAdapters;
using Microsoft.Extensions.Options;

Expand All @@ -29,6 +31,7 @@ public static ISystemWebAdapterBuilder AddRemoteAppClient(this ISystemWebAdapter
builder.Services.AddOptions<RemoteAppClientOptions>()
.ValidateDataAnnotations();

builder.Services.AddTransient<VirtualDirectoryHandler>();
builder.Services.AddHttpClient(RemoteConstants.HttpClientName)
.ConfigurePrimaryHttpMessageHandler(sp =>
{
Expand All @@ -42,6 +45,7 @@ public static ISystemWebAdapterBuilder AddRemoteAppClient(this ISystemWebAdapter
// Disable cookies in the HTTP client because the service will manage the cookie header directly
return new HttpClientHandler { UseCookies = false, AllowAutoRedirect = false };
})
.AddHttpMessageHandler<VirtualDirectoryHandler>()
.ConfigureHttpClient((sp, client) =>
{
var options = sp.GetRequiredService<IOptions<RemoteAppClientOptions>>().Value;
Expand Down Expand Up @@ -73,6 +77,37 @@ public static ISystemWebAdapterRemoteClientAppBuilder Configure(this ISystemWebA
return builder;
}

/// <summary>
/// <see cref="HttpClient.BaseAddress"/> is set automatically, but if this is supposed to have a path, then that gets
/// lost. This handler will append that back if necessary.
/// </summary>
private class VirtualDirectoryHandler : DelegatingHandler
{
private readonly string? _path;

public VirtualDirectoryHandler(IOptions<RemoteAppClientOptions> options)
{
_path = options.Value.RemoteAppUrl.AbsolutePath;

if (_path == "/")
{
_path = null;
}
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (_path is not null && request.RequestUri is { } uri)
{
var builder = new UriBuilder(uri);
builder.Path = $"{_path}{builder.Path}";
request.RequestUri = builder.Uri;
}

return base.SendAsync(request, cancellationToken);
}
}

private class Builder : ISystemWebAdapterRemoteClientAppBuilder
{
public Builder(IServiceCollection services)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ void IHttpModule.Dispose()

void IHttpModule.Init(HttpApplication context)
{
var appRelativePath = $"~{Path}";

context.PostMapRequestHandler += (s, _) =>
{
var context = ((HttpApplication)s).Context;

if (!string.Equals(context.Request.Path, Path, StringComparison.Ordinal))
// Compare against the AppRelativeCurrentExecutionFilePath to account for potential virtual directories
if (!string.Equals(context.Request.AppRelativeCurrentExecutionFilePath, appRelativePath, StringComparison.Ordinal))
{
return;
}
Expand Down