Files
Umbraco-CMS/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs

100 lines
3.9 KiB
C#
Raw Normal View History

using System;
2020-05-07 09:34:16 +02:00
using System.Collections.Generic;
using System.Threading;
2020-04-20 12:20:47 +02:00
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
2020-04-20 12:20:47 +02:00
namespace Umbraco.Cms.Web.Common.AspNetCore
2020-04-20 12:20:47 +02:00
{
public class AspNetCoreRequestAccessor : IRequestAccessor, INotificationHandler<UmbracoRequestBegin>
2020-04-20 12:20:47 +02:00
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly WebRoutingSettings _webRoutingSettings;
2020-05-07 09:34:16 +02:00
private readonly ISet<string> _applicationUrls = new HashSet<string>();
private Uri _currentApplicationUrl;
private object _initLocker = new object();
private bool _hasAppUrl = false;
private bool _isInit = false;
/// <summary>
/// Initializes a new instance of the <see cref="AspNetCoreRequestAccessor"/> class.
/// </summary>
public AspNetCoreRequestAccessor(
IHttpContextAccessor httpContextAccessor,
IOptions<WebRoutingSettings> webRoutingSettings)
2020-04-20 12:20:47 +02:00
{
_httpContextAccessor = httpContextAccessor;
_webRoutingSettings = webRoutingSettings.Value;
}
/// <inheritdoc/>
2020-04-20 12:20:47 +02:00
public string GetRequestValue(string name) => GetFormValue(name) ?? GetQueryStringValue(name);
private string GetFormValue(string name)
{
var request = _httpContextAccessor.GetRequiredHttpContext().Request;
if (!request.HasFormContentType) return null;
return request.Form[name];
}
2020-04-20 12:20:47 +02:00
/// <inheritdoc/>
2020-04-20 12:20:47 +02:00
public string GetQueryStringValue(string name) => _httpContextAccessor.GetRequiredHttpContext().Request.Query[name];
/// <inheritdoc/>
public Uri GetRequestUrl() => _httpContextAccessor.HttpContext != null ? new Uri(_httpContextAccessor.HttpContext.Request.GetEncodedUrl()) : null;
/// <inheritdoc/>
2020-05-07 09:34:16 +02:00
public Uri GetApplicationUrl()
{
// Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
2020-05-07 09:34:16 +02:00
// it changes the URL to `localhost:80` which actually doesn't work for pinging itself, it only works internally in Azure. The ironic part
// about this is that this is here specifically for the slot swap scenario https://issues.umbraco.org/issue/U4-10626
// see U4-10626 - in some cases we want to reset the application url
// (this is a simplified version of what was in 7.x)
// note: should this be optional? is it expensive?
if (!(_webRoutingSettings.UmbracoApplicationUrl is null))
{
return new Uri(_webRoutingSettings.UmbracoApplicationUrl);
}
var request = _httpContextAccessor.HttpContext?.Request;
if (request is null)
{
return _currentApplicationUrl;
}
2020-05-07 09:34:16 +02:00
var url = UriHelper.BuildAbsolute(request.Scheme, request.Host);
var change = url != null && !_applicationUrls.Contains(url);
if (change)
{
_applicationUrls.Add(url);
_currentApplicationUrl ??= new Uri(url);
}
return _currentApplicationUrl;
}
/// <summary>
/// This just initializes the application URL on first request attempt
/// TODO: This doesn't belong here, the GetApplicationUrl doesn't belong to IRequestAccessor
/// this should be part of middleware not a lazy init based on an INotification
/// </summary>
public void Handle(UmbracoRequestBegin notification)
=> LazyInitializer.EnsureInitialized(ref _hasAppUrl, ref _isInit, ref _initLocker, () =>
{
GetApplicationUrl();
return true;
});
2020-04-20 12:20:47 +02:00
}
}