@@ -48,9 +48,22 @@ public static class RAGFlowSharpServiceCollectionExtensions
4848 /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
4949 public static IServiceCollection AddRagflowSharp ( this IServiceCollection services ,
5050 Action < RAGFlowSharpOptions > setupAction )
51- {
51+ {
5252 return services . Configure ( setupAction ) . ConfigureRagflowSharp ( ) ;
53+ }
5354
55+ /// <summary>
56+ /// Adds and configures RAGFlow Sharp services with custom token provider to the specified <see cref="IServiceCollection"/>.
57+ /// </summary>
58+ /// <param name="services">The <see cref="IServiceCollection"/> to add services to.</param>
59+ /// <param name="setupAction">An action to configure the <see cref="RAGFlowSharpOptions"/>.</param>
60+ /// <param name="tokenProvider">Custom token provider delegate.</param>
61+ /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
62+ public static IServiceCollection AddRagflowSharp ( this IServiceCollection services ,
63+ Action < RAGFlowSharpOptions > setupAction ,
64+ Func < IServiceProvider , Task < TokenResult > > tokenProvider )
65+ {
66+ return services . Configure ( setupAction ) . ConfigureRagflowSharp ( tokenProvider ) ;
5467 }
5568
5669 /// <summary>
@@ -59,6 +72,18 @@ public static IServiceCollection AddRagflowSharp(this IServiceCollection service
5972 /// <param name="services">The <see cref="IServiceCollection"/> to configure services in.</param>
6073 /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
6174 public static IServiceCollection ConfigureRagflowSharp ( this IServiceCollection services )
75+ {
76+ return ConfigureRagflowSharp ( services , DefaultTokenProvider ) ;
77+ }
78+
79+ /// <summary>
80+ /// Configures RAGFlow Sharp services with a custom token provider.
81+ /// </summary>
82+ /// <param name="services">The <see cref="IServiceCollection"/> to configure services in.</param>
83+ /// <param name="tokenProvider">Custom token provider delegate.</param>
84+ /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
85+ public static IServiceCollection ConfigureRagflowSharp ( this IServiceCollection services ,
86+ Func < IServiceProvider , Task < TokenResult > > tokenProvider )
6287 {
6388 services . AddHttpApi < IRagflowApi > ( ( options , sp ) =>
6489 {
@@ -81,34 +106,74 @@ public static IServiceCollection ConfigureRagflowSharp(this IServiceCollection s
81106 options . KeyValueSerializeOptions . Converters . Add ( new JsonStringEnumConverter ( snakeCaseNamingPolicy ) ) ;
82107
83108 options . UseLogging = ragflowOptions . EnableLogging ;
84- } )
85- ;
109+ } ) ;
110+
111+ services . AddTokenProvider < IRagflowApi > ( tokenProvider ) ;
86112
87- services . AddTokenProvider < IRagflowApi > ( sp =>
113+ return services ;
114+ }
115+
116+ /// <summary>
117+ /// Default token provider implementation that extracts token from HTTP context and configuration.
118+ /// </summary>
119+ /// <param name="serviceProvider">The service provider.</param>
120+ /// <returns>A task that represents the asynchronous operation and contains the token result.</returns>
121+ private static Task < TokenResult > DefaultTokenProvider ( IServiceProvider serviceProvider )
122+ {
123+ var token = ExtractTokenFromHttpContext ( serviceProvider )
124+ ?? ExtractTokenFromConfiguration ( serviceProvider )
125+ ?? string . Empty ;
126+
127+ return Task . FromResult ( new TokenResult
88128 {
89- // 你可以在这里注入其他服务,比如 IHttpContextAccessor
90- var httpContextAccessor = sp . GetRequiredService < IHttpContextAccessor > ( ) ;
91- httpContextAccessor . HttpContext . Request . Headers . TryGetValue ( "Authorization" , out var authorizationHeader ) ;
92- httpContextAccessor . HttpContext . Request . Headers . TryGetValue ( "api_key" , out var apiKey ) ;
93- var token = apiKey . ToString ( ) ?? string . Empty ;
94- if ( ! StringValues . IsNullOrEmpty ( authorizationHeader ) && authorizationHeader . ToString ( ) . StartsWith ( "Bearer " ) )
95- {
96- token = authorizationHeader . ToString ( ) . Replace ( "Bearer " , "" ) ;
97- }
129+ Access_token = token ,
130+ Token_type = "Bearer"
131+ } ) ;
132+ }
98133
99- var ragflowOptions = sp . GetRequiredService < IOptions < RAGFlowSharpOptions > > ( ) . Value ;
100- if ( string . IsNullOrEmpty ( token ) && ! string . IsNullOrEmpty ( ragflowOptions . ApiKey ) )
134+ /// <summary>
135+ /// Extracts token from HTTP context headers (Authorization or api_key).
136+ /// </summary>
137+ /// <param name="serviceProvider">The service provider.</param>
138+ /// <returns>The extracted token or null if not found.</returns>
139+ private static string ? ExtractTokenFromHttpContext ( IServiceProvider serviceProvider )
140+ {
141+ var httpContextAccessor = serviceProvider . GetService < IHttpContextAccessor > ( ) ;
142+ if ( httpContextAccessor ? . HttpContext == null )
143+ return null ;
144+
145+ var headers = httpContextAccessor . HttpContext . Request . Headers ;
146+
147+ // 优先检查 Authorization header
148+ if ( headers . TryGetValue ( "Authorization" , out var authorizationHeader )
149+ && ! StringValues . IsNullOrEmpty ( authorizationHeader ) )
150+ {
151+ var authValue = authorizationHeader . ToString ( ) ;
152+ if ( authValue . StartsWith ( "Bearer " , StringComparison . OrdinalIgnoreCase ) )
101153 {
102- token = ragflowOptions . ApiKey ;
154+ return authValue . Substring ( 7 ) ; // Remove "Bearer " prefix
103155 }
104- return Task . FromResult ( new TokenResult
105- {
106- Access_token = token ,
107- Token_type = "Bearer"
108- } ) ! ;
109- } ) ;
156+ }
110157
111- return services ;
158+ // 检查 api_key header
159+ if ( headers . TryGetValue ( "api_key" , out var apiKeyHeader )
160+ && ! StringValues . IsNullOrEmpty ( apiKeyHeader ) )
161+ {
162+ return apiKeyHeader . ToString ( ) ;
163+ }
164+
165+ return null ;
166+ }
167+
168+ /// <summary>
169+ /// Extracts token from RAGFlow configuration options.
170+ /// </summary>
171+ /// <param name="serviceProvider">The service provider.</param>
172+ /// <returns>The configured API key or null if not set.</returns>
173+ private static string ? ExtractTokenFromConfiguration ( IServiceProvider serviceProvider )
174+ {
175+ var ragflowOptions = serviceProvider . GetRequiredService < IOptions < RAGFlowSharpOptions > > ( ) . Value ;
176+ return string . IsNullOrEmpty ( ragflowOptions . ApiKey ) ? null : ragflowOptions . ApiKey ;
112177 }
113178 }
114179}
0 commit comments