11using System ;
22using System . Collections . Generic ;
3+ using System . Runtime . CompilerServices ;
34using System . Threading . Tasks ;
45
56using Microsoft . AspNetCore . Http ;
910using Microsoft . Extensions . DependencyInjection ;
1011using Microsoft . Extensions . Logging ;
1112using Microsoft . Extensions . Options ;
13+ using Microsoft . Extensions . Primitives ;
1214using Microsoft . Net . Http . Headers ;
1315
1416namespace Cuture . AspNetCore . ResponseAutoWrapper ;
@@ -172,11 +174,61 @@ public async Task InvokeAsync(HttpContext context)
172174
173175 private Task WriteResponseWithFormatterAsync ( HttpContext context , object response )
174176 {
175- var formatterContext = new OutputFormatterWriteContext ( context ,
176- _httpResponseStreamWriterFactory . CreateWriter ,
177- response . GetType ( ) ,
178- response ) ;
177+ var formatterWriteContext = new OutputFormatterWriteContext ( context ,
178+ _httpResponseStreamWriterFactory . CreateWriter ,
179+ response . GetType ( ) ,
180+ response ) ;
181+
182+ if ( context . Request . Headers . TryGetValue ( HeaderNames . Accept , out var acceptValues )
183+ && acceptValues . Count > 0
184+ && ! EmptyOrHasWildcard ( acceptValues ) )
185+ {
186+ return WriteResponseWithSelectFormatterAsync ( context , formatterWriteContext ) ;
187+ }
188+
189+ // 有通配符,直接使用默认Formatter
190+ return _defaultOutputFormatter . WriteAsync ( formatterWriteContext ) ;
191+
192+ static bool EmptyOrHasWildcard ( in StringValues acceptValues )
193+ {
194+ // 检查通配符
195+ return acceptValues . Count switch
196+ {
197+ 1 => NullOrHasWildcard ( acceptValues , 0 ) ,
198+ 2 => NullOrHasWildcard ( acceptValues , 0 ) && NullOrHasWildcard ( acceptValues , 1 ) ,
199+ { } count => HasAnyWildcard ( acceptValues , count ) ,
200+ } ;
201+ }
179202
203+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
204+ static bool HasAnyWildcard ( in StringValues acceptValues , int count )
205+ {
206+ for ( int i = 0 ; i < count ; i ++ )
207+ {
208+ if ( NullOrHasWildcard ( acceptValues , i ) )
209+ {
210+ return true ;
211+ }
212+ }
213+ return false ;
214+ }
215+
216+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
217+ static bool NullOrHasWildcard ( in StringValues acceptValues , in int index )
218+ {
219+ var value = acceptValues [ index ] ;
220+ return value is null || value . Contains ( "*/*" , StringComparison . Ordinal ) ;
221+ }
222+ }
223+
224+ /// <summary>
225+ /// 选择Formatter进行响应
226+ /// </summary>
227+ /// <param name="context"></param>
228+ /// <param name="formatterWriteContext"></param>
229+ /// <returns></returns>
230+ private Task WriteResponseWithSelectFormatterAsync ( HttpContext context , OutputFormatterWriteContext formatterWriteContext )
231+ {
180232 var accepts = context . Request . Headers . TryGetValue ( HeaderNames . Accept , out var acceptValue )
181233 ? MediaTypeHeaderValue . TryParseList ( acceptValue , out var parsedAcceptValues )
182234 ? CreateMediaTypeCollection ( parsedAcceptValues )
@@ -185,12 +237,12 @@ private Task WriteResponseWithFormatterAsync(HttpContext context, object respons
185237
186238 var selectedFormatter = accepts is null
187239 ? _defaultOutputFormatter
188- : _outputFormatterSelector . SelectFormatter ( formatterContext ,
189- Array . Empty < IOutputFormatter > ( ) ,
190- accepts )
191- ?? _defaultOutputFormatter ;
240+ : _outputFormatterSelector . SelectFormatter ( formatterWriteContext ,
241+ Array . Empty < IOutputFormatter > ( ) ,
242+ accepts )
243+ ?? _defaultOutputFormatter ;
192244
193- return selectedFormatter . WriteAsync ( formatterContext ) ;
245+ return selectedFormatter . WriteAsync ( formatterWriteContext ) ;
194246 }
195247
196248 #endregion Internal
0 commit comments