Skip to content

Commit bcf8fbb

Browse files
committed
test(content-negotiation): respond 406 for bad accept header
1 parent 2dcceaf commit bcf8fbb

File tree

2 files changed

+74
-18
lines changed

2 files changed

+74
-18
lines changed
Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Microsoft.AspNetCore.Builder;
2+
using Microsoft.AspNetCore.Http;
3+
using Microsoft.Extensions.Primitives;
24

35
namespace JsonApiDotNetCore.Routing
46
{
@@ -8,24 +10,58 @@ public static IApplicationBuilder UseJsonApi(this IApplicationBuilder app)
810
{
911
app.Use(async (context, next) =>
1012
{
11-
var contentType = context.Request.ContentType;
12-
if (contentType != null)
13+
if (IsValid(context))
14+
await next.Invoke();
15+
});
16+
17+
app.UseMvc();
18+
19+
return app;
20+
}
21+
22+
private static bool IsValid(HttpContext context)
23+
{
24+
return IsValidContentTypeHeader(context) && IsValidAcceptHeader(context);
25+
}
26+
27+
private static bool IsValidContentTypeHeader(HttpContext context)
28+
{
29+
var contentType = context.Request.ContentType;
30+
if (contentType != null && ContainsMediaTypeParameters(contentType))
31+
{
32+
FlushResponse(context, 415);
33+
return false;
34+
}
35+
return true;
36+
}
37+
38+
private static bool IsValidAcceptHeader(HttpContext context)
39+
{
40+
var acceptHeaders = new StringValues();
41+
if (context.Request.Headers.TryGetValue("Accept", out acceptHeaders))
42+
{
43+
foreach (var acceptHeader in acceptHeaders)
1344
{
14-
var contentTypeArr = contentType.Split(';');
15-
if (contentTypeArr[0] == "application/vnd.api+json" && contentTypeArr.Length == 2)
45+
if (ContainsMediaTypeParameters(acceptHeader))
1646
{
17-
context.Response.StatusCode = 415;
18-
context.Response.Body.Flush();
19-
return;
47+
FlushResponse(context, 406);
48+
return false;
2049
}
2150
}
51+
}
52+
return true;
53+
}
2254

23-
await next.Invoke();
24-
});
25-
26-
app.UseMvc();
55+
private static bool ContainsMediaTypeParameters(string mediaType)
56+
{
57+
var mediaTypeArr = mediaType.Split(';');
58+
return (mediaTypeArr[0] == "application/vnd.api+json" && mediaTypeArr.Length == 2);
59+
}
2760

28-
return app;
61+
private static void FlushResponse(HttpContext context, int statusCode)
62+
{
63+
context.Response.StatusCode = statusCode;
64+
context.Response.Body.Flush();
2965
}
3066
}
3167
}

test/JsonApiDotNetCoreExampleTests/IntegrationTests/Spec/ContentNegotiation.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
using System;
2-
using System.Diagnostics.Contracts;
3-
using System.Globalization;
41
using System.Net;
52
using System.Net.Http;
63
using System.Net.Http.Headers;
7-
using System.Text;
84
using System.Threading.Tasks;
95
using DotNetCoreDocs;
106
using DotNetCoreDocs.Models;
117
using DotNetCoreDocs.Writers;
128
using JsonApiDotNetCoreExample;
139
using Microsoft.AspNetCore.Hosting;
14-
using Microsoft.AspNetCore.Mvc.Formatters.Internal;
1510
using Microsoft.AspNetCore.TestHost;
1611
using Xunit;
1712

@@ -61,13 +56,38 @@ public async Task Server_Responds_415_With_MediaType_Parameters()
6156
var request = new HttpRequestMessage(httpMethod, route);
6257
request.Content = new StringContent(string.Empty);
6358
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
64-
request.Content.Headers.ContentType.CharSet="ISO-8859-4";
59+
request.Content.Headers.ContentType.CharSet = "ISO-8859-4";
6560

6661
// act
6762
var response = await client.SendAsync(request);
6863

6964
// assert
7065
Assert.Equal(HttpStatusCode.UnsupportedMediaType, response.StatusCode);
7166
}
67+
68+
[Fact]
69+
public async Task ServerResponds_406_If_RequestAcceptHeader_Contains_MediaTypeParameters()
70+
{
71+
// arrange
72+
var builder = new WebHostBuilder()
73+
.UseStartup<Startup>();
74+
var httpMethod = new HttpMethod("GET");
75+
var route = "/api/v1/todo-items";
76+
var description = new RequestProperties("Server responds with 406...");
77+
var server = new TestServer(builder);
78+
var client = server.CreateClient();
79+
var acceptHeader = new MediaTypeWithQualityHeaderValue("application/vnd.api+json");
80+
acceptHeader.CharSet = "ISO-8859-4";
81+
client.DefaultRequestHeaders
82+
.Accept
83+
.Add(acceptHeader);
84+
var request = new HttpRequestMessage(httpMethod, route);
85+
86+
// act
87+
var response = await client.SendAsync(request);
88+
89+
// assert
90+
Assert.Equal(HttpStatusCode.NotAcceptable, response.StatusCode);
91+
}
7292
}
7393
}

0 commit comments

Comments
 (0)