Skip to content

Commit 6cb4cc2

Browse files
author
Bart Koelman
committed
Merge branch 'master' into various-fixes
2 parents 19b9918 + 6b16ea3 commit 6cb4cc2

File tree

2 files changed

+53
-56
lines changed

2 files changed

+53
-56
lines changed

src/Examples/GettingStarted/Startup.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ public void ConfigureServices(IServiceCollection services)
2222

2323
public void Configure(IApplicationBuilder app, SampleDbContext context)
2424
{
25-
context.Database.EnsureDeleted(); // indices need to be reset
25+
// indices need to be reset
26+
context.Database.EnsureDeleted();
27+
context.Database.EnsureCreated();
2628
app.UseJsonApi();
2729
}
2830
}

src/JsonApiDotNetCore/Middleware/CurrentRequestMiddleware.cs

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ namespace JsonApiDotNetCore.Middleware
2323
public sealed class CurrentRequestMiddleware
2424
{
2525
private readonly RequestDelegate _next;
26-
private HttpContext _httpContext;
27-
private IJsonApiOptions _options;
28-
private ICurrentRequest _currentRequest;
29-
private IResourceGraph _resourceGraph;
30-
private RouteValueDictionary _routeValues;
3126

3227
public CurrentRequestMiddleware(RequestDelegate next)
3328
{
@@ -40,47 +35,44 @@ public async Task Invoke(HttpContext httpContext,
4035
ICurrentRequest currentRequest,
4136
IResourceGraph resourceGraph)
4237
{
43-
_httpContext = httpContext;
44-
_options = options;
45-
_currentRequest = currentRequest;
46-
_resourceGraph = resourceGraph;
47-
_routeValues = httpContext.GetRouteData().Values;
38+
var routeValues = httpContext.GetRouteData().Values;
4839

49-
var resourceContext = CreateResourceContext(controllerResourceMapping);
40+
var resourceContext = CreateResourceContext(routeValues, controllerResourceMapping, resourceGraph);
5041
if (resourceContext != null)
5142
{
52-
if (!await ValidateContentTypeHeaderAsync() || !await ValidateAcceptHeaderAsync())
43+
if (!await ValidateContentTypeHeaderAsync(httpContext, options.SerializerSettings) ||
44+
!await ValidateAcceptHeaderAsync(httpContext, options.SerializerSettings))
5345
{
5446
return;
5547
}
5648

57-
SetupCurrentRequest(resourceContext);
49+
SetupCurrentRequest(currentRequest, resourceContext, routeValues, options, httpContext.Request);
5850

59-
_httpContext.SetJsonApiRequest();
51+
httpContext.SetJsonApiRequest();
6052
}
6153

6254
await _next(httpContext);
6355
}
6456

65-
private ResourceContext CreateResourceContext(IControllerResourceMapping controllerResourceMapping)
57+
private static ResourceContext CreateResourceContext(RouteValueDictionary routeValues,
58+
IControllerResourceMapping controllerResourceMapping, IResourceContextProvider resourceGraph)
6659
{
67-
var controllerName = (string)_routeValues["controller"];
60+
var controllerName = (string) routeValues["controller"];
6861
if (controllerName == null)
6962
{
7063
return null;
7164
}
7265

7366
var resourceType = controllerResourceMapping.GetAssociatedResource(controllerName);
74-
var resourceContext = _resourceGraph.GetResourceContext(resourceType);
75-
return resourceContext;
67+
return resourceGraph.GetResourceContext(resourceType);
7668
}
7769

78-
private async Task<bool> ValidateContentTypeHeaderAsync()
70+
private static async Task<bool> ValidateContentTypeHeaderAsync(HttpContext httpContext, JsonSerializerSettings serializerSettings)
7971
{
80-
var contentType = _httpContext.Request.ContentType;
72+
var contentType = httpContext.Request.ContentType;
8173
if (contentType != null && contentType != HeaderConstants.MediaType)
8274
{
83-
await FlushResponseAsync(_httpContext, new Error(HttpStatusCode.UnsupportedMediaType)
75+
await FlushResponseAsync(httpContext.Response, serializerSettings, new Error(HttpStatusCode.UnsupportedMediaType)
8476
{
8577
Title = "The specified Content-Type header value is not supported.",
8678
Detail = $"Please specify '{HeaderConstants.MediaType}' instead of '{contentType}' for the Content-Type header value."
@@ -91,9 +83,9 @@ private async Task<bool> ValidateContentTypeHeaderAsync()
9183
return true;
9284
}
9385

94-
private async Task<bool> ValidateAcceptHeaderAsync()
86+
private static async Task<bool> ValidateAcceptHeaderAsync(HttpContext httpContext, JsonSerializerSettings serializerSettings)
9587
{
96-
StringValues acceptHeaders = _httpContext.Request.Headers["Accept"];
88+
StringValues acceptHeaders = httpContext.Request.Headers["Accept"];
9789
if (!acceptHeaders.Any() || acceptHeaders == HeaderConstants.MediaType)
9890
{
9991
return true;
@@ -121,7 +113,7 @@ private async Task<bool> ValidateAcceptHeaderAsync()
121113

122114
if (!seenCompatibleMediaType)
123115
{
124-
await FlushResponseAsync(_httpContext, new Error(HttpStatusCode.NotAcceptable)
116+
await FlushResponseAsync(httpContext.Response, serializerSettings, new Error(HttpStatusCode.NotAcceptable)
125117
{
126118
Title = "The specified Accept header value does not contain any supported media types.",
127119
Detail = $"Please include '{HeaderConstants.MediaType}' in the Accept header values."
@@ -132,11 +124,11 @@ private async Task<bool> ValidateAcceptHeaderAsync()
132124
return true;
133125
}
134126

135-
private async Task FlushResponseAsync(HttpContext context, Error error)
127+
private static async Task FlushResponseAsync(HttpResponse httpResponse, JsonSerializerSettings serializerSettings, Error error)
136128
{
137-
context.Response.StatusCode = (int) error.StatusCode;
129+
httpResponse.StatusCode = (int) error.StatusCode;
138130

139-
JsonSerializer serializer = JsonSerializer.CreateDefault(_options.SerializerSettings);
131+
JsonSerializer serializer = JsonSerializer.CreateDefault(serializerSettings);
140132
serializer.ApplyErrorSettings();
141133

142134
// https://github.com/JamesNK/Newtonsoft.Json/issues/1193
@@ -149,78 +141,81 @@ private async Task FlushResponseAsync(HttpContext context, Error error)
149141
}
150142

151143
stream.Seek(0, SeekOrigin.Begin);
152-
await stream.CopyToAsync(context.Response.Body);
144+
await stream.CopyToAsync(httpResponse.Body);
153145
}
154146

155-
context.Response.Body.Flush();
147+
httpResponse.Body.Flush();
156148
}
157149

158-
private void SetupCurrentRequest(ResourceContext resourceContext)
150+
private static void SetupCurrentRequest(ICurrentRequest currentRequest, ResourceContext resourceContext,
151+
RouteValueDictionary routeValues, IJsonApiOptions options, HttpRequest httpRequest)
159152
{
160-
_currentRequest.SetRequestResource(resourceContext);
161-
_currentRequest.BaseId = GetBaseId();
162-
_currentRequest.BasePath = GetBasePath(resourceContext.ResourceName);
163-
_currentRequest.IsRelationshipPath = GetIsRelationshipPath();
164-
_currentRequest.RelationshipId = GetRelationshipId();
153+
currentRequest.SetRequestResource(resourceContext);
154+
currentRequest.BaseId = GetBaseId(routeValues);
155+
currentRequest.BasePath = GetBasePath(resourceContext.ResourceName, options, httpRequest);
156+
currentRequest.IsRelationshipPath = GetIsRelationshipPath(routeValues);
157+
currentRequest.RelationshipId = GetRelationshipId(currentRequest.IsRelationshipPath, httpRequest.Path.Value, options.Namespace);
165158

166-
if (_routeValues.TryGetValue("relationshipName", out object relationshipName))
159+
if (routeValues.TryGetValue("relationshipName", out object relationshipName))
167160
{
168-
_currentRequest.RequestRelationship = resourceContext.Relationships.SingleOrDefault(r => r.PublicRelationshipName == (string) relationshipName);
161+
currentRequest.RequestRelationship =
162+
resourceContext.Relationships.SingleOrDefault(relationship =>
163+
relationship.PublicRelationshipName == (string) relationshipName);
169164
}
170165
}
171166

172-
private string GetBaseId()
167+
private static string GetBaseId(RouteValueDictionary routeValues)
173168
{
174-
return _routeValues.TryGetValue("id", out var id) ? (string) id : null;
169+
return routeValues.TryGetValue("id", out var id) ? (string) id : null;
175170
}
176171

177-
private string GetBasePath(string resourceName)
172+
private static string GetBasePath(string resourceName, IJsonApiOptions options, HttpRequest httpRequest)
178173
{
179-
if (_options.RelativeLinks)
174+
if (options.RelativeLinks)
180175
{
181-
return _options.Namespace;
176+
return options.Namespace;
182177
}
183178

184-
var customRoute = GetCustomRoute(_httpContext.Request.Path.Value, resourceName);
185-
var toReturn = $"{_httpContext.Request.Scheme}://{_httpContext.Request.Host}/{_options.Namespace}";
179+
var customRoute = GetCustomRoute(httpRequest.Path.Value, resourceName, options.Namespace);
180+
var toReturn = $"{httpRequest.Scheme}://{httpRequest.Host}/{options.Namespace}";
186181
if (customRoute != null)
187182
{
188183
toReturn += $"/{customRoute}";
189184
}
190185
return toReturn;
191186
}
192187

193-
private string GetCustomRoute(string path, string resourceName)
188+
private static string GetCustomRoute(string path, string resourceName, string apiNamespace)
194189
{
195190
var trimmedComponents = path.Trim('/').Split('/').ToList();
196191
var resourceNameIndex = trimmedComponents.FindIndex(c => c == resourceName);
197192
var newComponents = trimmedComponents.Take(resourceNameIndex).ToArray();
198193
var customRoute = string.Join('/', newComponents);
199-
return customRoute == _options.Namespace ? null : customRoute;
194+
return customRoute == apiNamespace ? null : customRoute;
200195
}
201196

202-
private bool GetIsRelationshipPath()
197+
private static bool GetIsRelationshipPath(RouteValueDictionary routeValues)
203198
{
204-
var actionName = (string)_routeValues["action"];
199+
var actionName = (string)routeValues["action"];
205200
return actionName.ToLowerInvariant().Contains("relationships");
206201
}
207202

208-
private string GetRelationshipId()
203+
private static string GetRelationshipId(bool currentRequestIsRelationshipPath, string requestPath,
204+
string apiNamespace)
209205
{
210-
if (!_currentRequest.IsRelationshipPath)
206+
if (!currentRequestIsRelationshipPath)
211207
{
212208
return null;
213209
}
214210

215-
var components = SplitCurrentPath();
211+
var components = SplitCurrentPath(requestPath, apiNamespace);
216212
return components.ElementAtOrDefault(4);
217213
}
218214

219-
private string[] SplitCurrentPath()
215+
private static IEnumerable<string> SplitCurrentPath(string requestPath, string apiNamespace)
220216
{
221-
var path = _httpContext.Request.Path.Value;
222-
var ns = $"/{_options.Namespace}";
223-
var nonNameSpaced = path.Replace(ns, "");
217+
var namespacePrefix = $"/{apiNamespace}";
218+
var nonNameSpaced = requestPath.Replace(namespacePrefix, "");
224219
nonNameSpaced = nonNameSpaced.Trim('/');
225220
return nonNameSpaced.Split('/');
226221
}

0 commit comments

Comments
 (0)