diff --git a/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs
index 9b17bfc41..fb4c74dfa 100644
--- a/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs
+++ b/src/Squidex/Pipeline/CommandMiddlewares/ETagCommandMiddleware.cs
@@ -37,7 +37,7 @@ namespace Squidex.Pipeline.CommandMiddlewares
var headers = httpContextAccessor.HttpContext.Request.Headers;
- if (headers.TryGetValue(HeaderNames.ETag, out var etag) && !string.IsNullOrWhiteSpace(etag))
+ if (headers.TryGetValue(HeaderNames.IfMatch, out var etag) && !string.IsNullOrWhiteSpace(etag))
{
var etagValue = etag.ToString();
diff --git a/src/Squidex/Pipeline/ETagFilter.cs b/src/Squidex/Pipeline/ETagFilter.cs
index 587060944..d14561734 100644
--- a/src/Squidex/Pipeline/ETagFilter.cs
+++ b/src/Squidex/Pipeline/ETagFilter.cs
@@ -29,21 +29,23 @@ namespace Squidex.Pipeline
var httpContext = context.HttpContext;
- if (HttpMethods.IsGet(httpContext.Request.Method) &&
- httpContext.Response.StatusCode == 200 &&
- httpContext.Response.Headers.TryGetValue(HeaderNames.ETag, out var etag) && !string.IsNullOrWhiteSpace(etag))
+ if (httpContext.Response.Headers.TryGetValue(HeaderNames.ETag, out var etag) && !string.IsNullOrWhiteSpace(etag))
{
+ string etagValue = etag;
+
if (!options.Strong)
{
- httpContext.Response.Headers[HeaderNames.ETag] = "W/" + etag;
+ etagValue = "W/" + etag;
+
+ httpContext.Response.Headers[HeaderNames.ETag] = etagValue;
}
- if (httpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var noneMatch) && !string.IsNullOrWhiteSpace(noneMatch))
+ if (HttpMethods.IsGet(httpContext.Request.Method) &&
+ httpContext.Response.StatusCode == 200 &&
+ httpContext.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var noneMatch) && !string.IsNullOrWhiteSpace(noneMatch) &&
+ string.Equals(etagValue, noneMatch, System.StringComparison.Ordinal))
{
- if (string.Equals(etag, noneMatch, System.StringComparison.Ordinal))
- {
- resultContext.Result = new StatusCodeResult(304);
- }
+ resultContext.Result = new StatusCodeResult(304);
}
}
}
diff --git a/src/Squidex/app/shared/components/language-selector.component.html b/src/Squidex/app/shared/components/language-selector.component.html
index 9e80798dc..4215489e6 100644
--- a/src/Squidex/app/shared/components/language-selector.component.html
+++ b/src/Squidex/app/shared/components/language-selector.component.html
@@ -10,7 +10,7 @@
\ No newline at end of file
diff --git a/src/Squidex/app/shared/components/language-selector.component.scss b/src/Squidex/app/shared/components/language-selector.component.scss
index 10a1d636a..9568206f2 100644
--- a/src/Squidex/app/shared/components/language-selector.component.scss
+++ b/src/Squidex/app/shared/components/language-selector.component.scss
@@ -7,6 +7,9 @@
.iso-code {
font-family: monospace;
+}
+
+.iso-code-dropdown {
display: inline-block;
min-width: 40px;
max-width: 60px;
diff --git a/tests/Squidex.Tests/Pipeline/CommandMiddlewares/ETagCommandMiddlewareTests.cs b/tests/Squidex.Tests/Pipeline/CommandMiddlewares/ETagCommandMiddlewareTests.cs
index 043f6ee59..359147278 100644
--- a/tests/Squidex.Tests/Pipeline/CommandMiddlewares/ETagCommandMiddlewareTests.cs
+++ b/tests/Squidex.Tests/Pipeline/CommandMiddlewares/ETagCommandMiddlewareTests.cs
@@ -20,13 +20,13 @@ namespace Squidex.Pipeline.CommandMiddlewares
{
private readonly IHttpContextAccessor httpContextAccessor = A.Fake();
private readonly ICommandBus commandBus = A.Fake();
- private readonly IHeaderDictionary requestHeaders = new HeaderDictionary();
+ private readonly HttpContext httpContext = new DefaultHttpContext();
private readonly ETagCommandMiddleware sut;
public ETagCommandMiddlewareTests()
{
- A.CallTo(() => httpContextAccessor.HttpContext.Request.Headers)
- .Returns(requestHeaders);
+ A.CallTo(() => httpContextAccessor.HttpContext)
+ .Returns(httpContext);
sut = new ETagCommandMiddleware(httpContextAccessor);
}
@@ -48,7 +48,7 @@ namespace Squidex.Pipeline.CommandMiddlewares
[Fact]
public async Task Should_add_expected_version_to_command()
{
- requestHeaders[HeaderNames.ETag] = "13";
+ httpContext.Request.Headers[HeaderNames.IfMatch] = "13";
var command = new CreateContent();
var context = new CommandContext(command, commandBus);
@@ -61,7 +61,7 @@ namespace Squidex.Pipeline.CommandMiddlewares
[Fact]
public async Task Should_add_weak_etag_as_expected_version_to_command()
{
- requestHeaders[HeaderNames.ETag] = "W/13";
+ httpContext.Request.Headers[HeaderNames.IfMatch] = "W/13";
var command = new CreateContent();
var context = new CommandContext(command, commandBus);
diff --git a/tests/Squidex.Tests/Pipeline/ETagFilterTests.cs b/tests/Squidex.Tests/Pipeline/ETagFilterTests.cs
new file mode 100644
index 000000000..6e923b253
--- /dev/null
+++ b/tests/Squidex.Tests/Pipeline/ETagFilterTests.cs
@@ -0,0 +1,88 @@
+// ==========================================================================
+// Squidex Headless CMS
+// ==========================================================================
+// Copyright (c) Squidex UG (haftungsbeschraenkt)
+// All rights reserved. Licensed under the MIT license.
+// ==========================================================================
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using FakeItEasy;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Abstractions;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.Extensions.Options;
+using Microsoft.Net.Http.Headers;
+using Xunit;
+
+namespace Squidex.Pipeline
+{
+ public class ETagFilterTests
+ {
+ private readonly HttpContext httpContext = new DefaultHttpContext();
+ private readonly ActionExecutingContext executingContext;
+ private readonly ActionExecutedContext executedContext;
+ private readonly ETagFilter sut = new ETagFilter(Options.Create(new ETagOptions()));
+
+ public ETagFilterTests()
+ {
+ var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
+
+ var filters = new List();
+
+ executingContext = new ActionExecutingContext(actionContext, filters, new Dictionary(), this);
+ executedContext = new ActionExecutedContext(actionContext, filters, this)
+ {
+ Result = new OkResult()
+ };
+ }
+
+ [Fact]
+ public async Task Should_convert_strong_to_weak_tag()
+ {
+ httpContext.Response.Headers[HeaderNames.ETag] = "13";
+
+ await sut.OnActionExecutionAsync(executingContext, () => Task.FromResult(executedContext));
+
+ Assert.Equal("W/13", httpContext.Response.Headers[HeaderNames.ETag]);
+ }
+
+ [Fact]
+ public async Task Should_not_convert_empty_strong_to_weak_tag()
+ {
+ httpContext.Response.Headers[HeaderNames.ETag] = string.Empty;
+
+ await sut.OnActionExecutionAsync(executingContext, () => Task.FromResult(executedContext));
+
+ Assert.Null((string)httpContext.Response.Headers[HeaderNames.ETag]);
+ }
+
+ [Fact]
+ public async Task Should_return_304_for_same_etags()
+ {
+ httpContext.Request.Method = HttpMethods.Get;
+ httpContext.Request.Headers[HeaderNames.IfNoneMatch] = "W/13";
+
+ httpContext.Response.Headers[HeaderNames.ETag] = "13";
+
+ await sut.OnActionExecutionAsync(executingContext, () => Task.FromResult(executedContext));
+
+ Assert.Equal(304, (executedContext.Result as StatusCodeResult).StatusCode);
+ }
+
+ [Fact]
+ public async Task Should_not_return_304_for_different_etags()
+ {
+ httpContext.Request.Method = HttpMethods.Get;
+ httpContext.Request.Headers[HeaderNames.IfNoneMatch] = "W/11";
+
+ httpContext.Response.Headers[HeaderNames.ETag] = "13";
+
+ await sut.OnActionExecutionAsync(executingContext, () => Task.FromResult(executedContext));
+
+ Assert.Equal(200, (executedContext.Result as StatusCodeResult).StatusCode);
+ }
+ }
+}