Gets IsInternalRedirect working and documented, adds unit tests for the builder
This commit is contained in:
@@ -82,7 +82,7 @@ namespace Umbraco.Web.Routing
|
||||
// See http://issues.umbraco.org/issue/U4-8361#comment=67-30532
|
||||
// Setting automatic 301 redirects to not be cached because browsers cache these very aggressively which then leads
|
||||
// to problems if you rename a page back to it's original name or create a new page with the original name
|
||||
.SetCacheabilityNoCache(true)
|
||||
.SetNoCacheHeader(true)
|
||||
.SetCacheExtensions(new List<string> { "no-store, must-revalidate" })
|
||||
.SetHeaders(new Dictionary<string, string> { { "Pragma", "no-cache" }, { "Expires", "0" } });
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Web.Routing
|
||||
/// </summary>
|
||||
/// <remarks>Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to
|
||||
/// apply the internal redirect or not, when content is not the initial content.</remarks>
|
||||
bool IsInternalRedirectPublishedContent { get; } // TODO: Not sure what thsi is yet
|
||||
bool IsInternalRedirect { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template assigned to the request (if any)
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Web.Routing
|
||||
/// </summary>
|
||||
/// <remarks>Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to
|
||||
/// apply the internal redirect or not, when content is not the initial content.</remarks>
|
||||
bool IsInternalRedirectPublishedContent { get; }
|
||||
bool IsInternalRedirect { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content request http response status code.
|
||||
@@ -57,7 +57,7 @@ namespace Umbraco.Web.Routing
|
||||
IPublishedRequest Build();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the domain for the request
|
||||
/// Sets the domain for the request which also sets the culture
|
||||
/// </summary>
|
||||
IPublishedRequestBuilder SetDomain(DomainAndUri domain);
|
||||
|
||||
@@ -69,15 +69,15 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Sets the found <see cref="IPublishedContent"/> for the request
|
||||
/// </summary>
|
||||
/// <remarks>Setting the content clears the template and redirect</remarks>
|
||||
IPublishedRequestBuilder SetPublishedContent(IPublishedContent content);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the requested content, following an internal redirect.
|
||||
/// </summary>
|
||||
/// <param name="content">The requested content.</param>
|
||||
/// <remarks>Depending on <c>UmbracoSettings.InternalRedirectPreservesTemplate</c>, will
|
||||
/// preserve or reset the template, if any.</remarks>
|
||||
IPublishedRequestBuilder SetInternalRedirectPublishedContent(IPublishedContent content); // TODO: Need to figure this one out
|
||||
/// <remarks>Since this sets the content, it will clear the template</remarks>
|
||||
IPublishedRequestBuilder SetInternalRedirect(IPublishedContent content);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to set the template to use to display the requested content.
|
||||
@@ -123,7 +123,11 @@ namespace Umbraco.Web.Routing
|
||||
/// not be used, in due time.</remarks>
|
||||
IPublishedRequestBuilder SetResponseStatus(int code);
|
||||
|
||||
IPublishedRequestBuilder SetCacheabilityNoCache(bool cacheability);
|
||||
/// <summary>
|
||||
/// Sets the no-cache value to the Cache-Control header
|
||||
/// </summary>
|
||||
/// <param name="setHeader">True to set the header, false to not set it</param>
|
||||
IPublishedRequestBuilder SetNoCacheHeader(bool setHeader);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a list of Extensions to append to the Response.Cache object.
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
@@ -16,12 +13,13 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedRequest"/> class.
|
||||
/// </summary>
|
||||
public PublishedRequest(Uri uri, /*bool ignorePublishedContentCollisions, */IPublishedContent publishedContent, bool isInternalRedirectPublishedContent, ITemplate template, DomainAndUri domain, CultureInfo culture, string redirectUrl, int? responseStatusCode, IReadOnlyList<string> cacheExtensions, IReadOnlyDictionary<string, string> headers, bool cacheabilityNoCache)
|
||||
public PublishedRequest(Uri uri, IPublishedContent publishedContent, bool isInternalRedirect, ITemplate template, DomainAndUri domain, CultureInfo culture, string redirectUrl, int? responseStatusCode, IReadOnlyList<string> cacheExtensions, IReadOnlyDictionary<string, string> headers, bool cacheabilityNoCache)
|
||||
{
|
||||
Uri = uri ?? throw new ArgumentNullException(nameof(uri));
|
||||
// TODO: What is this?
|
||||
//IgnorePublishedContentCollisions = ignorePublishedContentCollisions;
|
||||
PublishedContent = publishedContent;
|
||||
IsInternalRedirectPublishedContent = isInternalRedirectPublishedContent;
|
||||
IsInternalRedirect = isInternalRedirect;
|
||||
Template = template;
|
||||
Domain = domain;
|
||||
Culture = culture;
|
||||
@@ -42,7 +40,7 @@ namespace Umbraco.Web.Routing
|
||||
public IPublishedContent PublishedContent { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsInternalRedirectPublishedContent { get; }
|
||||
public bool IsInternalRedirect { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ITemplate Template { get; }
|
||||
@@ -68,384 +66,4 @@ namespace Umbraco.Web.Routing
|
||||
/// <inheritdoc/>
|
||||
public bool CacheabilityNoCache { get; }
|
||||
}
|
||||
|
||||
// TODO: Kill this, but we need to port all of it's functionality
|
||||
public class PublishedRequestOld // : IPublishedRequest
|
||||
{
|
||||
private readonly IPublishedRouter _publishedRouter;
|
||||
private readonly WebRoutingSettings _webRoutingSettings;
|
||||
|
||||
private bool _readonly; // after prepared
|
||||
private bool _is404;
|
||||
private DomainAndUri _domain;
|
||||
private CultureInfo _culture;
|
||||
private IPublishedContent _publishedContent;
|
||||
private IPublishedContent _initialPublishedContent; // found by finders before 404, redirects, etc
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedRequest"/> class.
|
||||
/// </summary>
|
||||
public PublishedRequestOld(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptions<WebRoutingSettings> webRoutingSettings, Uri uri = null)
|
||||
{
|
||||
UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
|
||||
_publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter));
|
||||
_webRoutingSettings = webRoutingSettings.Value;
|
||||
Uri = uri ?? umbracoContext.CleanedUmbracoUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoContext.
|
||||
/// </summary>
|
||||
public IUmbracoContext UmbracoContext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cleaned up Uri used for routing.
|
||||
/// </summary>
|
||||
/// <remarks>The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc.</remarks>
|
||||
public Uri Uri { get; }
|
||||
|
||||
// utility for ensuring it is ok to set some properties
|
||||
public void EnsureWriteable()
|
||||
{
|
||||
if (_readonly)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot modify a PublishedRequest once it is read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool CacheabilityNoCache { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// Prepares the request.
|
||||
///// </summary>
|
||||
//public void Prepare()
|
||||
//{
|
||||
// _publishedRouter.PrepareRequest(this);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the Umbraco Backoffice should ignore a collision for this request.
|
||||
/// </summary>
|
||||
public bool IgnorePublishedContentCollisions { get; set; }
|
||||
|
||||
//#region Events
|
||||
|
||||
///// <summary>
|
||||
///// Triggers before the published content request is prepared.
|
||||
///// </summary>
|
||||
///// <remarks>When the event triggers, no preparation has been done. It is still possible to
|
||||
///// modify the request's Uri property, for example to restore its original, public-facing value
|
||||
///// that might have been modified by an in-between equipment such as a load-balancer.</remarks>
|
||||
//public static event EventHandler<EventArgs> Preparing;
|
||||
|
||||
///// <summary>
|
||||
///// Triggers once the published content request has been prepared, but before it is processed.
|
||||
///// </summary>
|
||||
///// <remarks>When the event triggers, preparation is done ie domain, culture, document, template,
|
||||
///// rendering engine, etc. have been setup. It is then possible to change anything, before
|
||||
///// the request is actually processed and rendered by Umbraco.</remarks>
|
||||
//public static event EventHandler<EventArgs> Prepared;
|
||||
|
||||
///// <summary>
|
||||
///// Triggers the Preparing event.
|
||||
///// </summary>
|
||||
//public void OnPreparing()
|
||||
//{
|
||||
// Preparing?.Invoke(this, EventArgs.Empty);
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Triggers the Prepared event.
|
||||
///// </summary>
|
||||
//public void OnPrepared()
|
||||
//{
|
||||
// Prepared?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// if (HasPublishedContent == false)
|
||||
// Is404 = true; // safety
|
||||
|
||||
// _readonly = true;
|
||||
//}
|
||||
|
||||
//#endregion
|
||||
|
||||
#region PublishedContent
|
||||
|
||||
///// <summary>
|
||||
///// Gets or sets the requested content.
|
||||
///// </summary>
|
||||
///// <remarks>Setting the requested content clears <c>Template</c>.</remarks>
|
||||
//public IPublishedContent PublishedContent
|
||||
//{
|
||||
// get { return _publishedContent; }
|
||||
// set
|
||||
// {
|
||||
// EnsureWriteable();
|
||||
// _publishedContent = value;
|
||||
// IsInternalRedirectPublishedContent = false;
|
||||
// TemplateModel = null;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the requested content, following an internal redirect.
|
||||
/// </summary>
|
||||
/// <param name="content">The requested content.</param>
|
||||
/// <remarks>Depending on <c>UmbracoSettings.InternalRedirectPreservesTemplate</c>, will
|
||||
/// preserve or reset the template, if any.</remarks>
|
||||
public void SetInternalRedirectPublishedContent(IPublishedContent content)
|
||||
{
|
||||
//if (content == null)
|
||||
// throw new ArgumentNullException(nameof(content));
|
||||
//EnsureWriteable();
|
||||
|
||||
//// unless a template has been set already by the finder,
|
||||
//// template should be null at that point.
|
||||
|
||||
//// IsInternalRedirect if IsInitial, or already IsInternalRedirect
|
||||
//var isInternalRedirect = IsInitialPublishedContent || IsInternalRedirectPublishedContent;
|
||||
|
||||
//// redirecting to self
|
||||
//if (content.Id == PublishedContent.Id) // neither can be null
|
||||
//{
|
||||
// // no need to set PublishedContent, we're done
|
||||
// IsInternalRedirectPublishedContent = isInternalRedirect;
|
||||
// return;
|
||||
//}
|
||||
|
||||
//// else
|
||||
|
||||
//// save
|
||||
//var template = Template;
|
||||
|
||||
//// set published content - this resets the template, and sets IsInternalRedirect to false
|
||||
//PublishedContent = content;
|
||||
//IsInternalRedirectPublishedContent = isInternalRedirect;
|
||||
|
||||
//// must restore the template if it's an internal redirect & the config option is set
|
||||
//if (isInternalRedirect && _webRoutingSettings.InternalRedirectPreservesTemplate)
|
||||
//{
|
||||
// // restore
|
||||
// TemplateModel = template;
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial requested content.
|
||||
/// </summary>
|
||||
/// <remarks>The initial requested content is the content that was found by the finders,
|
||||
/// before anything such as 404, redirect... took place.</remarks>
|
||||
public IPublishedContent InitialPublishedContent => _initialPublishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets value indicating whether the current published content is the initial one.
|
||||
/// </summary>
|
||||
public bool IsInitialPublishedContent => _initialPublishedContent != null && _initialPublishedContent == _publishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the current PublishedContent is the initial one.
|
||||
/// </summary>
|
||||
public void SetIsInitialPublishedContent()
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
// note: it can very well be null if the initial content was not found
|
||||
_initialPublishedContent = _publishedContent;
|
||||
IsInternalRedirectPublishedContent = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the current published content has been obtained
|
||||
/// from the initial published content following internal redirections exclusively.
|
||||
/// </summary>
|
||||
/// <remarks>Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to
|
||||
/// apply the internal redirect or not, when content is not the initial content.</remarks>
|
||||
public bool IsInternalRedirectPublishedContent { get; private set; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template model to use to display the requested content.
|
||||
/// </summary>
|
||||
public ITemplate Template { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the alias of the template to use to display the requested content.
|
||||
/// </summary>
|
||||
public string TemplateAlias => Template?.Alias;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request's domain.
|
||||
/// </summary>
|
||||
/// <remarks>Is a DomainAndUri object ie a standard Domain plus the fully qualified uri. For example,
|
||||
/// the <c>Domain</c> may contain "example.com" whereas the <c>Uri</c> will be fully qualified eg "http://example.com/".</remarks>
|
||||
public DomainAndUri Domain
|
||||
{
|
||||
get { return _domain; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_domain = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content request has a domain.
|
||||
/// </summary>
|
||||
public bool HasDomain => Domain != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request's culture.
|
||||
/// </summary>
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get { return _culture ?? Thread.CurrentThread.CurrentCulture; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
// note: do we want to have an ordered list of alternate cultures,
|
||||
// to allow for fallbacks when doing dictionary lookup and such?
|
||||
|
||||
|
||||
#region Status
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the requested content could not be found.
|
||||
/// </summary>
|
||||
/// <remarks>This is set in the <c>PublishedContentRequestBuilder</c> and can also be used in
|
||||
/// custom content finders or <c>Prepared</c> event handlers, where we want to allow developers
|
||||
/// to indicate a request is 404 but not to cancel it.</remarks>
|
||||
public bool Is404
|
||||
{
|
||||
get { return _is404; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_is404 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content request triggers a redirect (permanent or not).
|
||||
/// </summary>
|
||||
public bool IsRedirect => string.IsNullOrWhiteSpace(RedirectUrl) == false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the redirect is permanent.
|
||||
/// </summary>
|
||||
public bool IsRedirectPermanent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URL to redirect to, when the content request triggers a redirect.
|
||||
/// </summary>
|
||||
public string RedirectUrl { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a redirect (302).
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirect(string url)
|
||||
{
|
||||
EnsureWriteable();
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a permanent redirect (301).
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirectPermanent(string url)
|
||||
{
|
||||
EnsureWriteable();
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a redirect, with a specified status code.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <param name="status">The status code (300-308).</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirect(string url, int status)
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
if (status < 300 || status > 308)
|
||||
throw new ArgumentOutOfRangeException(nameof(status), "Valid redirection status codes 300-308.");
|
||||
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = (status == 301 || status == 308);
|
||||
if (status != 301 && status != 302) // default redirect statuses
|
||||
ResponseStatusCode = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request http response status code.
|
||||
/// </summary>
|
||||
/// <remarks>Does not actually set the http response status code, only registers that the response
|
||||
/// should use the specified code. The code will or will not be used, in due time.</remarks>
|
||||
public int ResponseStatusCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request http response status description.
|
||||
/// </summary>
|
||||
/// <remarks>Does not actually set the http response status description, only registers that the response
|
||||
/// should use the specified description. The description will or will not be used, in due time.</remarks>
|
||||
public string ResponseStatusDescription { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the http response status code, along with an optional associated description.
|
||||
/// </summary>
|
||||
/// <param name="code">The http status code.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
/// <remarks>Does not actually set the http response status code and description, only registers that
|
||||
/// the response should use the specified code and description. The code and description will or will
|
||||
/// not be used, in due time.</remarks>
|
||||
public void SetResponseStatus(int code, string description = null)
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
// .Status is deprecated
|
||||
// .SubStatusCode is IIS 7+ internal, ignore
|
||||
ResponseStatusCode = code;
|
||||
ResponseStatusDescription = description;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Response Cache
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <c>System.Web.HttpCacheability</c>
|
||||
/// </summary>
|
||||
// Note: we used to set a default value here but that would then be the default
|
||||
// for ALL requests, we shouldn't overwrite it though if people are using [OutputCache] for example
|
||||
// see: https://our.umbraco.com/forum/using-umbraco-and-getting-started/79715-output-cache-in-umbraco-752
|
||||
//public HttpCacheability Cacheability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of Extensions to append to the Response.Cache object.
|
||||
/// </summary>
|
||||
public List<string> CacheExtensions { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a dictionary of Headers to append to the Response object.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace Umbraco.Web.Routing
|
||||
private IReadOnlyDictionary<string, string> _headers;
|
||||
private bool _cacheability;
|
||||
private IReadOnlyList<string> _cacheExtensions;
|
||||
private IPublishedContent _internalRedirectContent;
|
||||
private string _redirectUrl;
|
||||
private HttpStatusCode? _responseStatus;
|
||||
private IPublishedContent _publishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedRequestBuilder"/> class.
|
||||
@@ -41,19 +41,28 @@ namespace Umbraco.Web.Routing
|
||||
public ITemplate Template { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsInternalRedirectPublishedContent { get; private set; } // TODO: Not sure what this is yet
|
||||
public bool IsInternalRedirect { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int? ResponseStatusCode => _responseStatus.HasValue ? (int?)_responseStatus : null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPublishedContent PublishedContent { get; private set; }
|
||||
public IPublishedContent PublishedContent
|
||||
{
|
||||
get => _publishedContent;
|
||||
private set
|
||||
{
|
||||
_publishedContent = value;
|
||||
IsInternalRedirect = false;
|
||||
Template = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPublishedRequest Build() => new PublishedRequest(
|
||||
Uri,
|
||||
PublishedContent,
|
||||
IsInternalRedirectPublishedContent,
|
||||
IsInternalRedirect,
|
||||
Template,
|
||||
Domain,
|
||||
Culture,
|
||||
@@ -64,7 +73,7 @@ namespace Umbraco.Web.Routing
|
||||
_cacheability);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPublishedRequestBuilder SetCacheabilityNoCache(bool cacheability)
|
||||
public IPublishedRequestBuilder SetNoCacheHeader(bool cacheability)
|
||||
{
|
||||
_cacheability = cacheability;
|
||||
return this;
|
||||
@@ -88,6 +97,7 @@ namespace Umbraco.Web.Routing
|
||||
public IPublishedRequestBuilder SetDomain(DomainAndUri domain)
|
||||
{
|
||||
Domain = domain;
|
||||
SetCulture(domain.Culture);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -99,9 +109,25 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IPublishedRequestBuilder SetInternalRedirectPublishedContent(IPublishedContent content)
|
||||
public IPublishedRequestBuilder SetInternalRedirect(IPublishedContent content)
|
||||
{
|
||||
_internalRedirectContent = content;
|
||||
// unless a template has been set already by the finder,
|
||||
// template should be null at that point.
|
||||
|
||||
// redirecting to self
|
||||
if (PublishedContent != null && content.Id == PublishedContent.Id)
|
||||
{
|
||||
// no need to set PublishedContent, we're done
|
||||
IsInternalRedirect = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
// else
|
||||
|
||||
// set published content - this resets the template, and sets IsInternalRedirect to false
|
||||
PublishedContent = content;
|
||||
IsInternalRedirect = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -109,6 +135,7 @@ namespace Umbraco.Web.Routing
|
||||
public IPublishedRequestBuilder SetPublishedContent(IPublishedContent content)
|
||||
{
|
||||
PublishedContent = content;
|
||||
IsInternalRedirect = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -152,7 +179,7 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
|
||||
// NOTE - can we still get it with whitespaces in it due to old legacy bugs?
|
||||
alias = alias.Replace(" ", "");
|
||||
alias = alias.Replace(" ", string.Empty);
|
||||
|
||||
ITemplate model = _fileService.GetTemplate(alias);
|
||||
if (model == null)
|
||||
|
||||
391
src/Umbraco.Core/Routing/PublishedRequestOld.cs
Normal file
391
src/Umbraco.Core/Routing/PublishedRequestOld.cs
Normal file
@@ -0,0 +1,391 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Core.Configuration.Models;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Web.Routing
|
||||
{
|
||||
// TODO: Kill this, but we need to port all of it's functionality
|
||||
public class PublishedRequestOld // : IPublishedRequest
|
||||
{
|
||||
private readonly IPublishedRouter _publishedRouter;
|
||||
private readonly WebRoutingSettings _webRoutingSettings;
|
||||
|
||||
private bool _readonly; // after prepared
|
||||
private bool _is404;
|
||||
private DomainAndUri _domain;
|
||||
private CultureInfo _culture;
|
||||
private IPublishedContent _publishedContent;
|
||||
private IPublishedContent _initialPublishedContent; // found by finders before 404, redirects, etc
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedRequest"/> class.
|
||||
/// </summary>
|
||||
public PublishedRequestOld(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptions<WebRoutingSettings> webRoutingSettings, Uri uri = null)
|
||||
{
|
||||
UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
|
||||
_publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter));
|
||||
_webRoutingSettings = webRoutingSettings.Value;
|
||||
Uri = uri ?? umbracoContext.CleanedUmbracoUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UmbracoContext.
|
||||
/// </summary>
|
||||
public IUmbracoContext UmbracoContext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the cleaned up Uri used for routing.
|
||||
/// </summary>
|
||||
/// <remarks>The cleaned up Uri has no virtual directory, no trailing slash, no .aspx extension, etc.</remarks>
|
||||
public Uri Uri { get; }
|
||||
|
||||
// utility for ensuring it is ok to set some properties
|
||||
public void EnsureWriteable()
|
||||
{
|
||||
if (_readonly)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot modify a PublishedRequest once it is read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool CacheabilityNoCache { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// Prepares the request.
|
||||
///// </summary>
|
||||
//public void Prepare()
|
||||
//{
|
||||
// _publishedRouter.PrepareRequest(this);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the Umbraco Backoffice should ignore a collision for this request.
|
||||
/// </summary>
|
||||
public bool IgnorePublishedContentCollisions { get; set; }
|
||||
|
||||
//#region Events
|
||||
|
||||
///// <summary>
|
||||
///// Triggers before the published content request is prepared.
|
||||
///// </summary>
|
||||
///// <remarks>When the event triggers, no preparation has been done. It is still possible to
|
||||
///// modify the request's Uri property, for example to restore its original, public-facing value
|
||||
///// that might have been modified by an in-between equipment such as a load-balancer.</remarks>
|
||||
//public static event EventHandler<EventArgs> Preparing;
|
||||
|
||||
///// <summary>
|
||||
///// Triggers once the published content request has been prepared, but before it is processed.
|
||||
///// </summary>
|
||||
///// <remarks>When the event triggers, preparation is done ie domain, culture, document, template,
|
||||
///// rendering engine, etc. have been setup. It is then possible to change anything, before
|
||||
///// the request is actually processed and rendered by Umbraco.</remarks>
|
||||
//public static event EventHandler<EventArgs> Prepared;
|
||||
|
||||
///// <summary>
|
||||
///// Triggers the Preparing event.
|
||||
///// </summary>
|
||||
//public void OnPreparing()
|
||||
//{
|
||||
// Preparing?.Invoke(this, EventArgs.Empty);
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// Triggers the Prepared event.
|
||||
///// </summary>
|
||||
//public void OnPrepared()
|
||||
//{
|
||||
// Prepared?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// if (HasPublishedContent == false)
|
||||
// Is404 = true; // safety
|
||||
|
||||
// _readonly = true;
|
||||
//}
|
||||
|
||||
//#endregion
|
||||
|
||||
#region PublishedContent
|
||||
|
||||
///// <summary>
|
||||
///// Gets or sets the requested content.
|
||||
///// </summary>
|
||||
///// <remarks>Setting the requested content clears <c>Template</c>.</remarks>
|
||||
//public IPublishedContent PublishedContent
|
||||
//{
|
||||
// get { return _publishedContent; }
|
||||
// set
|
||||
// {
|
||||
// EnsureWriteable();
|
||||
// _publishedContent = value;
|
||||
// IsInternalRedirectPublishedContent = false;
|
||||
// TemplateModel = null;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the requested content, following an internal redirect.
|
||||
/// </summary>
|
||||
/// <param name="content">The requested content.</param>
|
||||
/// <remarks>Depending on <c>UmbracoSettings.InternalRedirectPreservesTemplate</c>, will
|
||||
/// preserve or reset the template, if any.</remarks>
|
||||
public void SetInternalRedirectPublishedContent(IPublishedContent content)
|
||||
{
|
||||
//if (content == null)
|
||||
// throw new ArgumentNullException(nameof(content));
|
||||
//EnsureWriteable();
|
||||
|
||||
//// unless a template has been set already by the finder,
|
||||
//// template should be null at that point.
|
||||
|
||||
//// IsInternalRedirect if IsInitial, or already IsInternalRedirect
|
||||
//var isInternalRedirect = IsInitialPublishedContent || IsInternalRedirectPublishedContent;
|
||||
|
||||
//// redirecting to self
|
||||
//if (content.Id == PublishedContent.Id) // neither can be null
|
||||
//{
|
||||
// // no need to set PublishedContent, we're done
|
||||
// IsInternalRedirectPublishedContent = isInternalRedirect;
|
||||
// return;
|
||||
//}
|
||||
|
||||
//// else
|
||||
|
||||
//// save
|
||||
//var template = Template;
|
||||
|
||||
//// set published content - this resets the template, and sets IsInternalRedirect to false
|
||||
//PublishedContent = content;
|
||||
//IsInternalRedirectPublishedContent = isInternalRedirect;
|
||||
|
||||
//// must restore the template if it's an internal redirect & the config option is set
|
||||
//if (isInternalRedirect && _webRoutingSettings.InternalRedirectPreservesTemplate)
|
||||
//{
|
||||
// // restore
|
||||
// TemplateModel = template;
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial requested content.
|
||||
/// </summary>
|
||||
/// <remarks>The initial requested content is the content that was found by the finders,
|
||||
/// before anything such as 404, redirect... took place.</remarks>
|
||||
public IPublishedContent InitialPublishedContent => _initialPublishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets value indicating whether the current published content is the initial one.
|
||||
/// </summary>
|
||||
public bool IsInitialPublishedContent => _initialPublishedContent != null && _initialPublishedContent == _publishedContent;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the current PublishedContent is the initial one.
|
||||
/// </summary>
|
||||
public void SetIsInitialPublishedContent()
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
// note: it can very well be null if the initial content was not found
|
||||
_initialPublishedContent = _publishedContent;
|
||||
IsInternalRedirectPublishedContent = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the current published content has been obtained
|
||||
/// from the initial published content following internal redirections exclusively.
|
||||
/// </summary>
|
||||
/// <remarks>Used by PublishedContentRequestEngine.FindTemplate() to figure out whether to
|
||||
/// apply the internal redirect or not, when content is not the initial content.</remarks>
|
||||
public bool IsInternalRedirectPublishedContent { get; private set; }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template model to use to display the requested content.
|
||||
/// </summary>
|
||||
public ITemplate Template { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the alias of the template to use to display the requested content.
|
||||
/// </summary>
|
||||
public string TemplateAlias => Template?.Alias;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request's domain.
|
||||
/// </summary>
|
||||
/// <remarks>Is a DomainAndUri object ie a standard Domain plus the fully qualified uri. For example,
|
||||
/// the <c>Domain</c> may contain "example.com" whereas the <c>Uri</c> will be fully qualified eg "http://example.com/".</remarks>
|
||||
public DomainAndUri Domain
|
||||
{
|
||||
get { return _domain; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_domain = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content request has a domain.
|
||||
/// </summary>
|
||||
public bool HasDomain => Domain != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request's culture.
|
||||
/// </summary>
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get { return _culture ?? Thread.CurrentThread.CurrentCulture; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
// note: do we want to have an ordered list of alternate cultures,
|
||||
// to allow for fallbacks when doing dictionary lookup and such?
|
||||
|
||||
|
||||
#region Status
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the requested content could not be found.
|
||||
/// </summary>
|
||||
/// <remarks>This is set in the <c>PublishedContentRequestBuilder</c> and can also be used in
|
||||
/// custom content finders or <c>Prepared</c> event handlers, where we want to allow developers
|
||||
/// to indicate a request is 404 but not to cancel it.</remarks>
|
||||
public bool Is404
|
||||
{
|
||||
get { return _is404; }
|
||||
set
|
||||
{
|
||||
EnsureWriteable();
|
||||
_is404 = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the content request triggers a redirect (permanent or not).
|
||||
/// </summary>
|
||||
public bool IsRedirect => string.IsNullOrWhiteSpace(RedirectUrl) == false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the redirect is permanent.
|
||||
/// </summary>
|
||||
public bool IsRedirectPermanent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URL to redirect to, when the content request triggers a redirect.
|
||||
/// </summary>
|
||||
public string RedirectUrl { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a redirect (302).
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirect(string url)
|
||||
{
|
||||
EnsureWriteable();
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a permanent redirect (301).
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirectPermanent(string url)
|
||||
{
|
||||
EnsureWriteable();
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the content request should trigger a redirect, with a specified status code.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to redirect to.</param>
|
||||
/// <param name="status">The status code (300-308).</param>
|
||||
/// <remarks>Does not actually perform a redirect, only registers that the response should
|
||||
/// redirect. Redirect will or will not take place in due time.</remarks>
|
||||
public void SetRedirect(string url, int status)
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
if (status < 300 || status > 308)
|
||||
throw new ArgumentOutOfRangeException(nameof(status), "Valid redirection status codes 300-308.");
|
||||
|
||||
RedirectUrl = url;
|
||||
IsRedirectPermanent = (status == 301 || status == 308);
|
||||
if (status != 301 && status != 302) // default redirect statuses
|
||||
ResponseStatusCode = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request http response status code.
|
||||
/// </summary>
|
||||
/// <remarks>Does not actually set the http response status code, only registers that the response
|
||||
/// should use the specified code. The code will or will not be used, in due time.</remarks>
|
||||
public int ResponseStatusCode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content request http response status description.
|
||||
/// </summary>
|
||||
/// <remarks>Does not actually set the http response status description, only registers that the response
|
||||
/// should use the specified description. The description will or will not be used, in due time.</remarks>
|
||||
public string ResponseStatusDescription { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the http response status code, along with an optional associated description.
|
||||
/// </summary>
|
||||
/// <param name="code">The http status code.</param>
|
||||
/// <param name="description">The description.</param>
|
||||
/// <remarks>Does not actually set the http response status code and description, only registers that
|
||||
/// the response should use the specified code and description. The code and description will or will
|
||||
/// not be used, in due time.</remarks>
|
||||
public void SetResponseStatus(int code, string description = null)
|
||||
{
|
||||
EnsureWriteable();
|
||||
|
||||
// .Status is deprecated
|
||||
// .SubStatusCode is IIS 7+ internal, ignore
|
||||
ResponseStatusCode = code;
|
||||
ResponseStatusDescription = description;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Response Cache
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <c>System.Web.HttpCacheability</c>
|
||||
/// </summary>
|
||||
// Note: we used to set a default value here but that would then be the default
|
||||
// for ALL requests, we shouldn't overwrite it though if people are using [OutputCache] for example
|
||||
// see: https://our.umbraco.com/forum/using-umbraco-and-getting-started/79715-output-cache-in-umbraco-752
|
||||
//public HttpCacheability Cacheability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of Extensions to append to the Response.Cache object.
|
||||
/// </summary>
|
||||
public List<string> CacheExtensions { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a dictionary of Headers to append to the Response object.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -271,9 +271,7 @@ namespace Umbraco.Web.Routing
|
||||
// matching an existing domain
|
||||
_logger.LogDebug("{TracePrefix}Matches domain={Domain}, rootId={RootContentId}, culture={Culture}", tracePrefix, domainAndUri.Name, domainAndUri.ContentId, domainAndUri.Culture);
|
||||
|
||||
request
|
||||
.SetDomain(domainAndUri)
|
||||
.SetCulture(domainAndUri.Culture);
|
||||
request.SetDomain(domainAndUri);
|
||||
|
||||
// canonical? not implemented at the moment
|
||||
// if (...)
|
||||
@@ -368,7 +366,7 @@ namespace Umbraco.Web.Routing
|
||||
// so internal redirect, 404, etc has precedence over redirect
|
||||
|
||||
// handle not-found, redirects, access...
|
||||
HandlePublishedContent(request);
|
||||
HandlePublishedContent(request, foundContentByFinders);
|
||||
|
||||
// find a template
|
||||
FindTemplate(request, foundContentByFinders);
|
||||
@@ -404,11 +402,13 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Handles the published content (if any).
|
||||
/// </summary>
|
||||
/// <param name="request">The request builder.</param>
|
||||
/// <param name="contentFoundByFinders">If the content was found by the finders, before anything such as 404, redirect... took place.</param>
|
||||
/// <remarks>
|
||||
/// Handles "not found", internal redirects, access validation...
|
||||
/// things that must be handled in one place because they can create loops
|
||||
/// </remarks>
|
||||
private void HandlePublishedContent(IPublishedRequestBuilder request)
|
||||
private void HandlePublishedContent(IPublishedRequestBuilder request, bool contentFoundByFinders)
|
||||
{
|
||||
// because these might loop, we have to have some sort of infinite loop detection
|
||||
int i = 0, j = 0;
|
||||
@@ -435,7 +435,7 @@ namespace Umbraco.Web.Routing
|
||||
|
||||
// follow internal redirects as long as it's not running out of control ie infinite loop of some sort
|
||||
j = 0;
|
||||
while (FollowInternalRedirects(request) && j++ < maxLoop)
|
||||
while (FollowInternalRedirects(request, contentFoundByFinders) && j++ < maxLoop)
|
||||
{ }
|
||||
|
||||
// we're running out of control
|
||||
@@ -467,12 +467,14 @@ namespace Umbraco.Web.Routing
|
||||
/// <summary>
|
||||
/// Follows internal redirections through the <c>umbracoInternalRedirectId</c> document property.
|
||||
/// </summary>
|
||||
/// <param name="request">The request builder.</param>
|
||||
/// <param name="contentFoundByFinders">If the content was found by the finders, before anything such as 404, redirect... took place.</param>
|
||||
/// <returns>A value indicating whether redirection took place and led to a new published document.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</para>
|
||||
/// <para>As per legacy, if the redirect does not work, we just ignore it.</para>
|
||||
/// </remarks>
|
||||
private bool FollowInternalRedirects(IPublishedRequestBuilder request)
|
||||
private bool FollowInternalRedirects(IPublishedRequestBuilder request, bool contentFoundByFinders)
|
||||
{
|
||||
if (request.PublishedContent == null)
|
||||
{
|
||||
@@ -528,7 +530,18 @@ namespace Umbraco.Web.Routing
|
||||
}
|
||||
else
|
||||
{
|
||||
request.SetInternalRedirectPublishedContent(internalRedirectNode); // don't use .PublishedContent here
|
||||
// save since it will be cleared
|
||||
ITemplate template = request.Template;
|
||||
|
||||
request.SetInternalRedirect(internalRedirectNode); // don't use .PublishedContent here
|
||||
|
||||
// must restore the template if it's an internal redirect & the config option is set
|
||||
if (request.IsInternalRedirect && _webRoutingSettings.InternalRedirectPreservesTemplate)
|
||||
{
|
||||
// restore
|
||||
request.SetTemplate(template);
|
||||
}
|
||||
|
||||
redirect = true;
|
||||
_logger.LogDebug("FollowInternalRedirects: Redirecting to id={InternalRedirectId}", internalRedirectId);
|
||||
}
|
||||
@@ -615,7 +628,7 @@ namespace Umbraco.Web.Routing
|
||||
// does not apply
|
||||
// + optionally, apply the alternate template on internal redirects
|
||||
var useAltTemplate = contentFoundByFinders
|
||||
|| (_webRoutingSettings.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent);
|
||||
|| (_webRoutingSettings.InternalRedirectPreservesTemplate && request.IsInternalRedirect);
|
||||
|
||||
var altTemplate = useAltTemplate
|
||||
? _requestAccessor.GetRequestValue(Constants.Conventions.Url.AltTemplate)
|
||||
|
||||
@@ -49,10 +49,11 @@ namespace Umbraco.Web
|
||||
/// </summary>
|
||||
IDomainCache Domains { get; }
|
||||
|
||||
///// <summary>
|
||||
///// Gets or sets the PublishedRequest object
|
||||
///// </summary>
|
||||
//// TODO: Can we refactor this? The only nicer way would be to have a RouteRequest method directly on IUmbracoContext but that means adding another dep to the ctx
|
||||
/// <summary>
|
||||
/// Gets or sets the PublishedRequest object
|
||||
/// </summary>
|
||||
//// TODO: Can we refactor this so it's not a settable thing required for routing?
|
||||
//// The only nicer way would be to have a RouteRequest method directly on IUmbracoContext but that means adding another dep to the ctx/factory.
|
||||
IPublishedRequest PublishedRequest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core.Web.Routing
|
||||
{
|
||||
[TestFixture]
|
||||
public class PublishedRequestBuilderTests
|
||||
{
|
||||
private readonly Uri _baseUri = new Uri("https://example.com");
|
||||
|
||||
private IPublishedRequestBuilder GetBuilder() => new PublishedRequestBuilder(
|
||||
_baseUri,
|
||||
Mock.Of<IFileService>());
|
||||
|
||||
[Test]
|
||||
public void Setting_Published_Content_Clears_Template_And_Redirect()
|
||||
{
|
||||
IPublishedRequestBuilder sut = GetBuilder();
|
||||
sut.SetTemplate(Mock.Of<ITemplate>());
|
||||
|
||||
Assert.IsNotNull(sut.Template);
|
||||
|
||||
sut.SetInternalRedirect(Mock.Of<IPublishedContent>());
|
||||
|
||||
Assert.IsNull(sut.Template);
|
||||
Assert.IsTrue(sut.IsInternalRedirect);
|
||||
|
||||
sut.SetTemplate(Mock.Of<ITemplate>());
|
||||
sut.SetPublishedContent(Mock.Of<IPublishedContent>());
|
||||
|
||||
Assert.IsNull(sut.Template);
|
||||
Assert.IsFalse(sut.IsInternalRedirect);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Setting_Domain_Also_Sets_Culture()
|
||||
{
|
||||
IPublishedRequestBuilder sut = GetBuilder();
|
||||
|
||||
Assert.IsNull(sut.Culture);
|
||||
|
||||
sut.SetDomain(
|
||||
new DomainAndUri(
|
||||
new Domain(1, "test", 2, CultureInfo.GetCultureInfo("en-AU"), false), new Uri("https://example.com/en-au")));
|
||||
|
||||
Assert.IsNotNull(sut.Domain);
|
||||
Assert.IsNotNull(sut.Culture);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Builds_All_Values()
|
||||
{
|
||||
IPublishedRequestBuilder sut = GetBuilder();
|
||||
|
||||
IPublishedContent content = Mock.Of<IPublishedContent>(x => x.Id == 1);
|
||||
ITemplate template = Mock.Of<ITemplate>(x => x.Id == 1);
|
||||
string[] cacheExt = new[] { "must-revalidate" };
|
||||
var auCulture = CultureInfo.GetCultureInfo("en-AU");
|
||||
var usCulture = CultureInfo.GetCultureInfo("en-US");
|
||||
var domain = new DomainAndUri(
|
||||
new Domain(1, "test", 2, auCulture, false), new Uri("https://example.com/en-au"));
|
||||
IReadOnlyDictionary<string, string> headers = new Dictionary<string, string> { ["Hello"] = "world" };
|
||||
var redirect = "https://test.com";
|
||||
|
||||
sut
|
||||
.SetNoCacheHeader(true)
|
||||
.SetCacheExtensions(cacheExt)
|
||||
.SetDomain(domain)
|
||||
.SetCulture(usCulture)
|
||||
.SetHeaders(headers)
|
||||
.SetInternalRedirect(content)
|
||||
.SetRedirect(redirect)
|
||||
.SetTemplate(template);
|
||||
|
||||
IPublishedRequest request = sut.Build();
|
||||
|
||||
Assert.AreEqual(true, request.CacheabilityNoCache);
|
||||
Assert.AreEqual(cacheExt, request.CacheExtensions);
|
||||
Assert.AreEqual(usCulture, request.Culture);
|
||||
Assert.AreEqual(domain, request.Domain);
|
||||
Assert.AreEqual(headers, request.Headers);
|
||||
Assert.AreEqual(true, request.IsInternalRedirect);
|
||||
Assert.AreEqual(content, request.PublishedContent);
|
||||
Assert.AreEqual(redirect, request.RedirectUrl);
|
||||
Assert.AreEqual(302, request.ResponseStatusCode);
|
||||
Assert.AreEqual(template, request.Template);
|
||||
Assert.AreEqual(_baseUri, request.Uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user