@@ -68,16 +68,35 @@ protected virtual (RangeItemHeaderValue? range, long rangeLength, bool serveBody
68
68
DateTimeOffset ? lastModified = null ,
69
69
EntityTagHeaderValue ? etag = null )
70
70
{
71
- if ( context == null )
71
+ return SetHeadersAndLog (
72
+ context . HttpContext ,
73
+ result ,
74
+ fileLength ,
75
+ enableRangeProcessing ,
76
+ lastModified ,
77
+ etag ,
78
+ Logger ) ;
79
+ }
80
+
81
+ internal static ( RangeItemHeaderValue ? range , long rangeLength , bool serveBody ) SetHeadersAndLog (
82
+ HttpContext httpContext ,
83
+ FileResult result ,
84
+ long ? fileLength ,
85
+ bool enableRangeProcessing ,
86
+ DateTimeOffset ? lastModified ,
87
+ EntityTagHeaderValue ? etag ,
88
+ ILogger logger )
89
+ {
90
+ if ( httpContext == null )
72
91
{
73
- throw new ArgumentNullException ( nameof ( context ) ) ;
92
+ throw new ArgumentNullException ( nameof ( httpContext ) ) ;
74
93
}
75
94
if ( result == null )
76
95
{
77
96
throw new ArgumentNullException ( nameof ( result ) ) ;
78
97
}
79
-
80
- var request = context . HttpContext . Request ;
98
+
99
+ var request = httpContext . Request ;
81
100
var httpRequestHeaders = request . GetTypedHeaders ( ) ;
82
101
83
102
// Since the 'Last-Modified' and other similar http date headers are rounded down to whole seconds,
@@ -87,9 +106,9 @@ protected virtual (RangeItemHeaderValue? range, long rangeLength, bool serveBody
87
106
lastModified = RoundDownToWholeSeconds ( lastModified . Value ) ;
88
107
}
89
108
90
- var preconditionState = GetPreconditionState ( httpRequestHeaders , lastModified , etag ) ;
109
+ var preconditionState = GetPreconditionState ( httpRequestHeaders , lastModified , etag , logger ) ;
91
110
92
- var response = context . HttpContext . Response ;
111
+ var response = httpContext . Response ;
93
112
SetLastModifiedAndEtagHeaders ( response , lastModified , etag ) ;
94
113
95
114
// Short circuit if the preconditional headers process to 304 (NotModified) or 412 (PreconditionFailed)
@@ -104,8 +123,8 @@ protected virtual (RangeItemHeaderValue? range, long rangeLength, bool serveBody
104
123
return ( range : null , rangeLength : 0 , serveBody : false ) ;
105
124
}
106
125
107
- SetContentType ( context , result ) ;
108
- SetContentDispositionHeader ( context , result ) ;
126
+ SetContentType ( httpContext , result ) ;
127
+ SetContentDispositionHeader ( httpContext , result ) ;
109
128
110
129
if ( fileLength . HasValue )
111
130
{
@@ -125,27 +144,27 @@ protected virtual (RangeItemHeaderValue? range, long rangeLength, bool serveBody
125
144
// range should be processed and Range headers should be set
126
145
if ( ( HttpMethods . IsHead ( request . Method ) || HttpMethods . IsGet ( request . Method ) )
127
146
&& ( preconditionState == PreconditionState . Unspecified || preconditionState == PreconditionState . ShouldProcess )
128
- && ( IfRangeValid ( httpRequestHeaders , lastModified , etag ) ) )
147
+ && ( IfRangeValid ( httpRequestHeaders , lastModified , etag , logger ) ) )
129
148
{
130
- return SetRangeHeaders ( context , httpRequestHeaders , fileLength . Value ) ;
149
+ return SetRangeHeaders ( httpContext , httpRequestHeaders , fileLength . Value , logger ) ;
131
150
}
132
151
}
133
152
else
134
153
{
135
- Logger . NotEnabledForRangeProcessing ( ) ;
154
+ logger . NotEnabledForRangeProcessing ( ) ;
136
155
}
137
156
}
138
157
139
158
return ( range : null , rangeLength : 0 , serveBody : ! HttpMethods . IsHead ( request . Method ) ) ;
140
159
}
141
160
142
- private static void SetContentType ( ActionContext context , FileResult result )
161
+ private static void SetContentType ( HttpContext httpContext , FileResult result )
143
162
{
144
- var response = context . HttpContext . Response ;
163
+ var response = httpContext . Response ;
145
164
response . ContentType = result . ContentType ;
146
165
}
147
166
148
- private static void SetContentDispositionHeader ( ActionContext context , FileResult result )
167
+ private static void SetContentDispositionHeader ( HttpContext httpContext , FileResult result )
149
168
{
150
169
if ( ! string . IsNullOrEmpty ( result . FileDownloadName ) )
151
170
{
@@ -156,7 +175,7 @@ private static void SetContentDispositionHeader(ActionContext context, FileResul
156
175
// basis for the actual filename, where possible.
157
176
var contentDisposition = new ContentDispositionHeaderValue ( "attachment" ) ;
158
177
contentDisposition . SetHttpFileName ( result . FileDownloadName ) ;
159
- context . HttpContext . Response . Headers . ContentDisposition = contentDisposition . ToString ( ) ;
178
+ httpContext . Response . Headers . ContentDisposition = contentDisposition . ToString ( ) ;
160
179
}
161
180
}
162
181
@@ -178,10 +197,11 @@ private static void SetAcceptRangeHeader(HttpResponse response)
178
197
response . Headers . AcceptRanges = AcceptRangeHeaderValue ;
179
198
}
180
199
181
- internal bool IfRangeValid (
200
+ internal static bool IfRangeValid (
182
201
RequestHeaders httpRequestHeaders ,
183
202
DateTimeOffset ? lastModified ,
184
- EntityTagHeaderValue ? etag )
203
+ EntityTagHeaderValue ? etag ,
204
+ ILogger logger )
185
205
{
186
206
// 14.27 If-Range
187
207
var ifRange = httpRequestHeaders . IfRange ;
@@ -196,13 +216,13 @@ internal bool IfRangeValid(
196
216
{
197
217
if ( lastModified . HasValue && lastModified > ifRange . LastModified )
198
218
{
199
- Logger . IfRangeLastModifiedPreconditionFailed ( lastModified , ifRange . LastModified ) ;
219
+ logger . IfRangeLastModifiedPreconditionFailed ( lastModified , ifRange . LastModified ) ;
200
220
return false ;
201
221
}
202
222
}
203
223
else if ( etag != null && ifRange . EntityTag != null && ! ifRange . EntityTag . Compare ( etag , useStrongComparison : true ) )
204
224
{
205
- Logger . IfRangeETagPreconditionFailed ( etag , ifRange . EntityTag ) ;
225
+ logger . IfRangeETagPreconditionFailed ( etag , ifRange . EntityTag ) ;
206
226
return false ;
207
227
}
208
228
}
@@ -211,10 +231,11 @@ internal bool IfRangeValid(
211
231
}
212
232
213
233
// Internal for testing
214
- internal PreconditionState GetPreconditionState (
234
+ internal static PreconditionState GetPreconditionState (
215
235
RequestHeaders httpRequestHeaders ,
216
236
DateTimeOffset ? lastModified ,
217
- EntityTagHeaderValue ? etag )
237
+ EntityTagHeaderValue ? etag ,
238
+ ILogger logger )
218
239
{
219
240
var ifMatchState = PreconditionState . Unspecified ;
220
241
var ifNoneMatchState = PreconditionState . Unspecified ;
@@ -234,7 +255,7 @@ internal PreconditionState GetPreconditionState(
234
255
235
256
if ( ifMatchState == PreconditionState . PreconditionFailed )
236
257
{
237
- Logger . IfMatchPreconditionFailed ( etag ) ;
258
+ logger . IfMatchPreconditionFailed ( etag ) ;
238
259
}
239
260
}
240
261
@@ -269,7 +290,7 @@ internal PreconditionState GetPreconditionState(
269
290
270
291
if ( ifUnmodifiedSinceState == PreconditionState . PreconditionFailed )
271
292
{
272
- Logger . IfUnmodifiedSincePreconditionFailed ( lastModified , ifUnmodifiedSince ) ;
293
+ logger . IfUnmodifiedSincePreconditionFailed ( lastModified , ifUnmodifiedSince ) ;
273
294
}
274
295
}
275
296
@@ -316,22 +337,23 @@ private static PreconditionState GetMaxPreconditionState(params PreconditionStat
316
337
return max ;
317
338
}
318
339
319
- private ( RangeItemHeaderValue ? range , long rangeLength , bool serveBody ) SetRangeHeaders (
320
- ActionContext context ,
340
+ private static ( RangeItemHeaderValue ? range , long rangeLength , bool serveBody ) SetRangeHeaders (
341
+ HttpContext httpContext ,
321
342
RequestHeaders httpRequestHeaders ,
322
- long fileLength )
343
+ long fileLength ,
344
+ ILogger logger )
323
345
{
324
- var response = context . HttpContext . Response ;
346
+ var response = httpContext . Response ;
325
347
var httpResponseHeaders = response . GetTypedHeaders ( ) ;
326
- var serveBody = ! HttpMethods . IsHead ( context . HttpContext . Request . Method ) ;
348
+ var serveBody = ! HttpMethods . IsHead ( httpContext . Request . Method ) ;
327
349
328
350
// Range may be null for empty range header, invalid ranges, parsing errors, multiple ranges
329
351
// and when the file length is zero.
330
352
var ( isRangeRequest , range ) = RangeHelper . ParseRange (
331
- context . HttpContext ,
353
+ httpContext ,
332
354
httpRequestHeaders ,
333
355
fileLength ,
334
- Logger ) ;
356
+ logger ) ;
335
357
336
358
if ( ! isRangeRequest )
337
359
{
@@ -397,6 +419,11 @@ protected static ILogger CreateLogger<T>(ILoggerFactory factory)
397
419
/// <param name="rangeLength">The range length.</param>
398
420
/// <returns>The async task.</returns>
399
421
protected static async Task WriteFileAsync ( HttpContext context , Stream fileStream , RangeItemHeaderValue ? range , long rangeLength )
422
+ {
423
+ await WriteFileAsyncInternal ( context , fileStream , range , rangeLength ) ;
424
+ }
425
+
426
+ internal static async Task WriteFileAsyncInternal ( HttpContext context , Stream fileStream , RangeItemHeaderValue ? range , long rangeLength )
400
427
{
401
428
var outputStream = context . Response . Body ;
402
429
using ( fileStream )
0 commit comments