1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
- using System . IO ;
4
+ using System . Buffers ;
5
5
using System . Net . Http . Headers ;
6
6
using System . Runtime . InteropServices . JavaScript ;
7
7
using System . Threading ;
@@ -17,47 +17,53 @@ internal static partial class BrowserHttpInterop
17
17
[ JSImport ( "INTERNAL.http_wasm_supports_streaming_response" ) ]
18
18
public static partial bool SupportsStreamingResponse ( ) ;
19
19
20
- [ JSImport ( "INTERNAL.http_wasm_create_abort_controler " ) ]
21
- public static partial JSObject CreateAbortController ( ) ;
20
+ [ JSImport ( "INTERNAL.http_wasm_create_controller " ) ]
21
+ public static partial JSObject CreateController ( ) ;
22
22
23
23
[ JSImport ( "INTERNAL.http_wasm_abort_request" ) ]
24
24
public static partial void AbortRequest (
25
- JSObject abortController ) ;
25
+ JSObject httpController ) ;
26
26
27
27
[ JSImport ( "INTERNAL.http_wasm_abort_response" ) ]
28
28
public static partial void AbortResponse (
29
- JSObject fetchResponse ) ;
30
-
31
- [ JSImport ( "INTERNAL.http_wasm_create_transform_stream" ) ]
32
- public static partial JSObject CreateTransformStream ( ) ;
29
+ JSObject httpController ) ;
33
30
34
31
[ JSImport ( "INTERNAL.http_wasm_transform_stream_write" ) ]
35
32
public static partial Task TransformStreamWrite (
36
- JSObject transformStream ,
33
+ JSObject httpController ,
37
34
IntPtr bufferPtr ,
38
35
int bufferLength ) ;
39
36
37
+ public static unsafe Task TransformStreamWriteUnsafe ( JSObject httpController , ReadOnlyMemory < byte > buffer , Buffers . MemoryHandle handle )
38
+ => TransformStreamWrite ( httpController , ( nint ) handle . Pointer , buffer . Length ) ;
39
+
40
40
[ JSImport ( "INTERNAL.http_wasm_transform_stream_close" ) ]
41
41
public static partial Task TransformStreamClose (
42
- JSObject transformStream ) ;
43
-
44
- [ JSImport ( "INTERNAL.http_wasm_transform_stream_abort" ) ]
45
- public static partial void TransformStreamAbort (
46
- JSObject transformStream ) ;
42
+ JSObject httpController ) ;
47
43
48
44
[ JSImport ( "INTERNAL.http_wasm_get_response_header_names" ) ]
49
45
private static partial string [ ] _GetResponseHeaderNames (
50
- JSObject fetchResponse ) ;
46
+ JSObject httpController ) ;
51
47
52
48
[ JSImport ( "INTERNAL.http_wasm_get_response_header_values" ) ]
53
49
private static partial string [ ] _GetResponseHeaderValues (
54
- JSObject fetchResponse ) ;
50
+ JSObject httpController ) ;
51
+
52
+ [ JSImport ( "INTERNAL.http_wasm_get_response_status" ) ]
53
+ public static partial int GetResponseStatus (
54
+ JSObject httpController ) ;
55
+
56
+ [ JSImport ( "INTERNAL.http_wasm_get_response_type" ) ]
57
+ public static partial string GetResponseType (
58
+ JSObject httpController ) ;
55
59
56
- public static void GetResponseHeaders ( JSObject fetchResponse , HttpHeaders resposeHeaders , HttpHeaders contentHeaders )
60
+ public static void GetResponseHeaders ( JSObject httpController , HttpHeaders resposeHeaders , HttpHeaders contentHeaders )
57
61
{
58
- string [ ] headerNames = _GetResponseHeaderNames ( fetchResponse ) ;
59
- string [ ] headerValues = _GetResponseHeaderValues ( fetchResponse ) ;
62
+ string [ ] headerNames = _GetResponseHeaderNames ( httpController ) ;
63
+ string [ ] headerValues = _GetResponseHeaderValues ( httpController ) ;
60
64
65
+ // Some of the headers may not even be valid header types in .NET thus we use TryAddWithoutValidation
66
+ // CORS will only allow access to certain headers on browser.
61
67
for ( int i = 0 ; i < headerNames . Length ; i ++ )
62
68
{
63
69
if ( ! resposeHeaders . TryAddWithoutValidation ( headerNames [ i ] , headerValues [ i ] ) )
@@ -67,43 +73,38 @@ public static void GetResponseHeaders(JSObject fetchResponse, HttpHeaders respos
67
73
}
68
74
}
69
75
70
-
71
76
[ JSImport ( "INTERNAL.http_wasm_fetch" ) ]
72
- public static partial Task < JSObject > Fetch (
77
+ public static partial Task Fetch (
78
+ JSObject httpController ,
73
79
string uri ,
74
80
string [ ] headerNames ,
75
81
string [ ] headerValues ,
76
82
string [ ] optionNames ,
77
- [ JSMarshalAs < JSType . Array < JSType . Any > > ] object ? [ ] optionValues ,
78
- JSObject abortControler ) ;
83
+ [ JSMarshalAs < JSType . Array < JSType . Any > > ] object ? [ ] optionValues ) ;
79
84
80
85
[ JSImport ( "INTERNAL.http_wasm_fetch_stream" ) ]
81
- public static partial Task < JSObject > Fetch (
86
+ public static partial Task FetchStream (
87
+ JSObject httpController ,
82
88
string uri ,
83
89
string [ ] headerNames ,
84
90
string [ ] headerValues ,
85
91
string [ ] optionNames ,
86
- [ JSMarshalAs < JSType . Array < JSType . Any > > ] object ? [ ] optionValues ,
87
- JSObject abortControler ,
88
- JSObject transformStream ) ;
92
+ [ JSMarshalAs < JSType . Array < JSType . Any > > ] object ? [ ] optionValues ) ;
89
93
90
94
[ JSImport ( "INTERNAL.http_wasm_fetch_bytes" ) ]
91
- private static partial Task < JSObject > FetchBytes (
95
+ private static partial Task FetchBytes (
96
+ JSObject httpController ,
92
97
string uri ,
93
98
string [ ] headerNames ,
94
99
string [ ] headerValues ,
95
100
string [ ] optionNames ,
96
101
[ JSMarshalAs < JSType . Array < JSType . Any > > ] object ? [ ] optionValues ,
97
- JSObject abortControler ,
98
102
IntPtr bodyPtr ,
99
103
int bodyLength ) ;
100
104
101
- public static unsafe Task < JSObject > Fetch ( string uri , string [ ] headerNames , string [ ] headerValues , string [ ] optionNames , object ? [ ] optionValues , JSObject abortControler , byte [ ] body )
105
+ public static unsafe Task FetchBytes ( JSObject httpController , string uri , string [ ] headerNames , string [ ] headerValues , string [ ] optionNames , object ? [ ] optionValues , MemoryHandle pinBuffer , int bodyLength )
102
106
{
103
- fixed ( byte * ptr = body )
104
- {
105
- return FetchBytes ( uri , headerNames , headerValues , optionNames , optionValues , abortControler , ( IntPtr ) ptr , body . Length ) ;
106
- }
107
+ return FetchBytes ( httpController , uri , headerNames , headerValues , optionNames , optionValues , ( IntPtr ) pinBuffer . Pointer , bodyLength ) ;
107
108
}
108
109
109
110
[ JSImport ( "INTERNAL.http_wasm_get_streamed_response_bytes" ) ]
@@ -112,6 +113,10 @@ public static partial Task<int> GetStreamedResponseBytes(
112
113
IntPtr bufferPtr ,
113
114
int bufferLength ) ;
114
115
116
+ public static unsafe Task < int > GetStreamedResponseBytesUnsafe ( JSObject jsController , Memory < byte > buffer , MemoryHandle handle )
117
+ => GetStreamedResponseBytes ( jsController , ( IntPtr ) handle . Pointer , buffer . Length ) ;
118
+
119
+
115
120
[ JSImport ( "INTERNAL.http_wasm_get_response_length" ) ]
116
121
public static partial Task < int > GetResponseLength (
117
122
JSObject fetchResponse ) ;
@@ -122,8 +127,10 @@ public static partial int GetResponseBytes(
122
127
[ JSMarshalAs < JSType . MemoryView > ] Span < byte > buffer ) ;
123
128
124
129
125
- public static async ValueTask CancelationHelper ( Task promise , CancellationToken cancellationToken , JSObject ? fetchResponse = null )
130
+ public static async Task CancellationHelper ( Task promise , CancellationToken cancellationToken , JSObject jsController )
126
131
{
132
+ Http . CancellationHelper . ThrowIfCancellationRequested ( cancellationToken ) ;
133
+
127
134
if ( promise . IsCompletedSuccessfully )
128
135
{
129
136
return ;
@@ -132,46 +139,43 @@ public static async ValueTask CancelationHelper(Task promise, CancellationToken
132
139
{
133
140
using ( var operationRegistration = cancellationToken . Register ( static s =>
134
141
{
135
- ( Task _promise , JSObject ? _fetchResponse ) = ( ( Task , JSObject ? ) ) s ! ;
136
- CancelablePromise . CancelPromise ( _promise , static ( JSObject ? __fetchResponse ) =>
142
+ ( Task _promise , JSObject _jsController ) = ( ( Task , JSObject ) ) s ! ;
143
+ CancelablePromise . CancelPromise ( _promise , static ( JSObject __jsController ) =>
137
144
{
138
- if ( __fetchResponse != null )
145
+ if ( ! __jsController . IsDisposed )
139
146
{
140
- AbortResponse ( __fetchResponse ) ;
147
+ AbortResponse ( __jsController ) ;
141
148
}
142
- } , _fetchResponse ) ;
143
- } , ( promise , fetchResponse ) ) )
149
+ } , _jsController ) ;
150
+ } , ( promise , jsController ) ) )
144
151
{
145
152
await promise . ConfigureAwait ( true ) ;
146
153
}
147
154
}
148
155
catch ( OperationCanceledException oce ) when ( cancellationToken . IsCancellationRequested )
149
156
{
150
- throw CancellationHelper . CreateOperationCanceledException ( oce , cancellationToken ) ;
157
+ Http . CancellationHelper . ThrowIfCancellationRequested ( oce , cancellationToken ) ;
151
158
}
152
159
catch ( JSException jse )
153
160
{
154
161
if ( jse . Message . StartsWith ( "AbortError" , StringComparison . Ordinal ) )
155
162
{
156
- throw CancellationHelper . CreateOperationCanceledException ( jse , CancellationToken . None ) ;
157
- }
158
- if ( cancellationToken . IsCancellationRequested )
159
- {
160
- throw CancellationHelper . CreateOperationCanceledException ( jse , cancellationToken ) ;
163
+ throw Http . CancellationHelper . CreateOperationCanceledException ( jse , CancellationToken . None ) ;
161
164
}
165
+ Http . CancellationHelper . ThrowIfCancellationRequested ( jse , cancellationToken ) ;
162
166
throw new HttpRequestException ( jse . Message , jse ) ;
163
167
}
164
168
}
165
169
166
- public static async ValueTask < T > CancelationHelper < T > ( Task < T > promise , CancellationToken cancellationToken , JSObject ? fetchResponse = null )
170
+ public static async Task < T > CancellationHelper < T > ( Task < T > promise , CancellationToken cancellationToken , JSObject jsController )
167
171
{
172
+ Http . CancellationHelper . ThrowIfCancellationRequested ( cancellationToken ) ;
168
173
if ( promise . IsCompletedSuccessfully )
169
174
{
170
175
return promise . Result ;
171
176
}
172
- await CancelationHelper ( ( Task ) promise , cancellationToken , fetchResponse ) . ConfigureAwait ( true ) ;
173
- return await promise . ConfigureAwait ( true ) ;
177
+ await CancellationHelper ( ( Task ) promise , cancellationToken , jsController ) . ConfigureAwait ( false ) ;
178
+ return promise . Result ;
174
179
}
175
180
}
176
-
177
181
}
0 commit comments