11using System . Net . Http . Headers ;
2- using System . Net . Http . Json ;
3- using System . Text ;
42using System . Text . Json ;
5- using System . Text . Json . Serialization ;
63using ClaudeCodeProxy . Abstraction ;
74
85namespace ClaudeCodeProxy . Core . Extensions ;
96
107public static class HttpClientExtensions
118{
12- public static async Task < HttpResponseMessage > HttpRequestRaw ( this HttpClient httpClient , string url ,
13- object ? postData ,
14- string token )
15- {
16- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
17-
18- if ( postData != null )
19- {
20- if ( postData is HttpContent data )
21- {
22- req . Content = data ;
23- }
24- else
25- {
26- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
27- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
28- req . Content = stringContent ;
29- }
30- }
31-
32- if ( ! string . IsNullOrEmpty ( token ) )
33- {
34- req . Headers . Add ( "Authorization" , $ "Bearer { token } ") ;
35- }
9+ private static readonly MediaTypeHeaderValue JsonMediaType =
10+ new ( "application/json" ) { CharSet = "utf-8" } ;
3611
37- var response = await httpClient . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead ) ;
38-
39- return response ;
40- }
41-
42- public static async Task < HttpResponseMessage > HttpRequestRaw ( this HttpClient httpClient , string url ,
43- object ? postData ,
44- string token , string tokenKey )
12+ private static async ValueTask < HttpContent > CreateJsonContentAsync ( object value )
4513 {
46- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
47-
48- if ( postData != null )
49- {
50- if ( postData is HttpContent data )
51- {
52- req . Content = data ;
53- }
54- else
55- {
56- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
57- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
58- req . Content = stringContent ;
59- }
60- }
61-
62- if ( ! string . IsNullOrEmpty ( token ) )
63- {
64- req . Headers . Add ( tokenKey , token ) ;
65- }
66-
67-
68- var response = await httpClient . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead ) ;
69-
70- return response ;
14+ var ms = new MemoryStream ( 16 * 1024 ) ; // 预分配减少扩容
15+ await JsonSerializer . SerializeAsync ( ms , value , value . GetType ( ) , ThorJsonSerializer . DefaultOptions )
16+ . ConfigureAwait ( false ) ;
17+ ms . Position = 0 ;
18+
19+ var content = new StreamContent ( ms ) ;
20+ content . Headers . ContentType = JsonMediaType ;
21+ return content ;
7122 }
7223
73- public static async Task < HttpResponseMessage > HttpRequestRaw ( this HttpClient httpClient , string url ,
74- object ? postData ,
75- string token , Dictionary < string , string > headers )
24+ public static async Task < HttpResponseMessage > HttpRequestRaw < T > ( this HttpClient httpClient , string url ,
25+ T postData , string token , Dictionary < string , string > headers ) where T : class
7626 {
77- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
78-
79- if ( postData != null )
27+ var req = new HttpRequestMessage ( HttpMethod . Post , url )
8028 {
81- if ( postData is HttpContent data )
82- {
83- req . Content = data ;
84- }
85- else
86- {
87- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
88- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
89- req . Content = stringContent ;
90- }
91- }
29+ Content = await CreateJsonContentAsync ( postData ) . ConfigureAwait ( false )
30+ } ;
9231
93- if ( ! string . IsNullOrEmpty ( token ) )
32+ if ( ! string . IsNullOrWhiteSpace ( token ) )
9433 {
95- req . Headers . Add ( "Authorization ", $ "Bearer { token } " ) ;
34+ req . Headers . Authorization = new AuthenticationHeaderValue ( "Bearer ", token ) ;
9635 }
9736
98- foreach ( var header in headers . Where ( header => ! req . Headers . Contains ( header . Key ) ) )
37+ foreach ( var kv in headers )
9938 {
100- req . Headers . Add ( header . Key , header . Value ) ;
39+ if ( ! req . Headers . Contains ( kv . Key ) )
40+ req . Headers . TryAddWithoutValidation ( kv . Key , kv . Value ) ;
10141 }
10242
103-
104- var response = await httpClient . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead ) ;
105-
106- return response ;
43+ return await httpClient . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead ) . ConfigureAwait ( false ) ;
10744 }
10845
109- public static async Task < HttpResponseMessage > HttpRequestRaw ( this HttpClient httpClient , HttpRequestMessage req ,
110- object ? postData )
46+ public static async Task < HttpResponseMessage > PostJsonAsync < T > ( this HttpClient httpClient , string url ,
47+ T ? postData , string token , Dictionary < string , string > headers ) where T : class
11148 {
112- if ( postData != null )
49+ var req = new HttpRequestMessage ( HttpMethod . Post , url )
11350 {
114- if ( postData is HttpContent data )
115- {
116- req . Content = data ;
117- }
118- else
119- {
120- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
121- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
122- req . Content = stringContent ;
123- }
124- }
125-
126- var response = await httpClient . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead ) ;
51+ Content = await CreateJsonContentAsync ( postData ) . ConfigureAwait ( false )
52+ } ;
12753
128- return response ;
129- }
130-
131- public static async Task < HttpResponseMessage > PostJsonAsync ( this HttpClient httpClient , string url ,
132- object ? postData ,
133- string token )
134- {
135- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
136-
137- if ( postData != null )
138- {
139- if ( postData is HttpContent data )
140- {
141- req . Content = data ;
142- }
143- else
144- {
145- var stringContent =
146- new StringContent ( JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ,
147- Encoding . UTF8 , "application/json" ) ;
148- req . Content = stringContent ;
149- }
150- }
151-
152- if ( ! string . IsNullOrEmpty ( token ) )
153- {
154- req . Headers . Add ( "Authorization" , $ "Bearer { token } ") ;
155- }
156-
157- return await httpClient . SendAsync ( req ) ;
158- }
159-
160- public static async Task < HttpResponseMessage > PostJsonAsync ( this HttpClient httpClient , string url ,
161- object ? postData ,
162- string token , Dictionary < string , string > headers )
163- {
164- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
165-
166- if ( postData != null )
54+ if ( ! string . IsNullOrWhiteSpace ( token ) )
16755 {
168- if ( postData is HttpContent data )
169- {
170- req . Content = data ;
171- }
172- else
173- {
174- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
175- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
176-
177- if ( url . StartsWith ( "https://chatgpt.com/backend-api/codex" ) )
178- {
179- stringContent . Headers . ContentType = new MediaTypeHeaderValue ( "application/json" ) ;
180- }
181-
182- req . Content = stringContent ;
183- }
56+ req . Headers . Authorization = new AuthenticationHeaderValue ( "Bearer" , token ) ;
18457 }
18558
186- if ( ! string . IsNullOrEmpty ( token ) )
187- {
188- req . Headers . Add ( "Authorization" , $ "Bearer { token } ") ;
189- }
190-
191- foreach ( var header in headers . Where ( header => ! req . Headers . Contains ( header . Key ) ) )
192- {
193- req . Headers . Add ( header . Key , header . Value ) ;
194- }
195-
196- if ( url . StartsWith ( "https://chatgpt.com/backend-api/codex" ) )
197- {
198- req . Headers . Add ( "Host" , "chatgpt.com" ) ;
199- }
200-
201-
202- return await httpClient . SendAsync ( req ) ;
203- }
204-
205- public static Task < HttpResponseMessage > PostJsonAsync ( this HttpClient httpClient , string url , object ? postData ,
206- string token , string tokenKey )
207- {
208- HttpRequestMessage req = new ( HttpMethod . Post , url ) ;
209-
210- if ( postData != null )
59+ foreach ( var kv in headers )
21160 {
212- if ( postData is HttpContent data )
213- {
214- req . Content = data ;
215- }
216- else
217- {
218- string jsonContent = JsonSerializer . Serialize ( postData , ThorJsonSerializer . DefaultOptions ) ;
219- var stringContent = new StringContent ( jsonContent , Encoding . UTF8 , "application/json" ) ;
220- req . Content = stringContent ;
221- }
61+ if ( ! req . Headers . Contains ( kv . Key ) )
62+ req . Headers . TryAddWithoutValidation ( kv . Key , kv . Value ) ;
22263 }
22364
224- if ( ! string . IsNullOrEmpty ( token ) )
65+ if ( url . StartsWith ( "https://chatgpt.com/backend-api/codex" , StringComparison . OrdinalIgnoreCase ) )
22566 {
226- req . Headers . Add ( tokenKey , token ) ;
67+ req . Headers . Host = "chatgpt.com" ;
22768 }
22869
229- return httpClient . SendAsync ( req ) ;
70+ return await httpClient . SendAsync ( req ) . ConfigureAwait ( false ) ;
23071 }
23172}
0 commit comments