@@ -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