Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit af4d4a6

Browse files
only accept hal json
1 parent 5dd68a4 commit af4d4a6

3 files changed

Lines changed: 84 additions & 0 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
namespace SqlStreamStore.HAL.Tests
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Net;
7+
using System.Net.Http;
8+
using System.Net.Http.Headers;
9+
using System.Threading.Tasks;
10+
using Shouldly;
11+
using Xunit;
12+
13+
public class AcceptHeaderTests : IDisposable
14+
{
15+
private readonly SqlStreamStoreHalMiddlewareFixture _fixture;
16+
17+
public AcceptHeaderTests()
18+
{
19+
_fixture = new SqlStreamStoreHalMiddlewareFixture();
20+
}
21+
22+
public static IEnumerable<object[]> NotAcceptableCases()
23+
{
24+
var requestUris = new[] { "/stream", "/streams/a-stream", "/" };
25+
var methods = new[]
26+
{
27+
HttpMethod.Get,
28+
HttpMethod.Head,
29+
HttpMethod.Options,
30+
HttpMethod.Post,
31+
HttpMethod.Delete
32+
};
33+
var mediaTypes = new[] { "text/html", "application/hal", "application/hal+xml" };
34+
35+
return from requestUri in requestUris
36+
from method in methods
37+
from mediaType in mediaTypes
38+
select new object[] { requestUri, method, new MediaTypeWithQualityHeaderValue(mediaType) };
39+
}
40+
41+
[Theory, MemberData(nameof(NotAcceptableCases))]
42+
public async Task accept_other_than_hal_json_are_not_acceptable(
43+
string requestUri,
44+
HttpMethod method,
45+
MediaTypeWithQualityHeaderValue mediaType)
46+
{
47+
using(var response = await _fixture.HttpClient.SendAsync(new HttpRequestMessage(method, requestUri)
48+
{
49+
Headers = { Accept = { mediaType } }
50+
}))
51+
{
52+
response.StatusCode.ShouldBe(HttpStatusCode.NotAcceptable);
53+
}
54+
}
55+
56+
public void Dispose() => _fixture.Dispose();
57+
}
58+
}

src/SqlStreamStore.HAL/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public static class ContentTypes
1414
{
1515
public const string Json = "application/json";
1616
public const string HalJson = "application/hal+json";
17+
public const string Any = "*/*";
1718
}
1819
}
1920

src/SqlStreamStore.HAL/SqlStreamStoreHalMiddleware.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using System;
44
using System.Linq;
5+
using System.Net.Http.Headers;
56
using System.Threading.Tasks;
67
using Halcyon.HAL;
78
using Microsoft.Owin;
@@ -49,6 +50,29 @@ public static class SqlStreamStoreHalMiddleware
4950
return next(env);
5051
};
5152

53+
54+
private static MidFunc AcceptOnlyHalJson => next => env =>
55+
{
56+
var context = new OwinContext(env);
57+
58+
var accept = context.Request.Accept?.Split(',')
59+
.Select(value => MediaTypeWithQualityHeaderValue.TryParse(value, out var header)
60+
? header.MediaType
61+
: null)
62+
?? Enumerable.Empty<string>();
63+
64+
return accept.Any(header => header == Constants.Headers.ContentTypes.HalJson
65+
|| header == Constants.Headers.ContentTypes.Any)
66+
? next(env)
67+
: context.WriteHalResponse(new Response(new HALResponse(new
68+
{
69+
type = "Not Acceptable",
70+
title = "Not Acceptable",
71+
detail = $"The server only understands {Constants.Headers.ContentTypes.HalJson}."
72+
}),
73+
406));
74+
};
75+
5276
private static MidFunc Index => next => env =>
5377
{
5478
var context = new OwinContext(env);
@@ -72,6 +96,7 @@ public static MidFunc UseSqlStreamStoreHal(IStreamStore streamStore)
7296
.Use(ExceptionHandlingMiddleware.HandleExceptions)
7397
.Use(AccessControl)
7498
.Use(AddReasonPhrase)
99+
.Use(AcceptOnlyHalJson)
75100
.Use(Index)
76101
.Map("/stream", inner => inner
77102
.Use(ReadAllStreamMiddleware.UseStreamStore(streamStore))

0 commit comments

Comments
 (0)