@@ -3,6 +3,8 @@ import { h1NoCache, noCache, createUrl, AbortController, AbortError, FetchError
3
3
import { serialize as serializeCookie , parse as parseCookie } from 'cookie' ;
4
4
import log from '../logging.js' ;
5
5
6
+ // TODO: review, use keepAliveNoCache, review keepAlive: true (default in many options).
7
+
6
8
const fetchKeepAlive = noCache ( {
7
9
h1 : {
8
10
keepAlive : true
@@ -20,13 +22,29 @@ const fetchH1KeepAlive = h1NoCache({
20
22
rejectUnauthorized : false // By default skip auth check for all.
21
23
} ) . fetch ;
22
24
25
+ const fetchIPv4H1KeepAlive = h1NoCache ( {
26
+ h1 : {
27
+ keepAlive : true ,
28
+ family : 4
29
+ } ,
30
+ rejectUnauthorized : false // By default skip auth check for all.
31
+ } ) . fetch ;
32
+
23
33
const fetchAuthorized = noCache ( {
24
34
h2 : {
25
35
enablePush : false
26
36
}
27
37
} ) . fetch ; // `rejectUnauthorized: true` - by `fetch` default.
38
+
28
39
const fetchH1Authorized = h1NoCache ( ) . fetch ; // `rejectUnauthorized: true` - by `fetch` default.
29
40
41
+ const fetchIPv4H1Authorized = h1NoCache ( {
42
+ h1 : {
43
+ keepAlive : true ,
44
+ family : 4
45
+ }
46
+ } ) . fetch ; // `rejectUnauthorized: true` - by `fetch` default.
47
+
30
48
const { fetch } = noCache ( {
31
49
h2 : {
32
50
enablePush : false
@@ -38,7 +56,15 @@ const fetchH1 = h1NoCache({
38
56
rejectUnauthorized : false // By default skip auth check for all.
39
57
} ) . fetch ;
40
58
41
- function doFetch ( fetch_func , h1_fetch_func , options ) {
59
+ const fetchIPv4H1 = h1NoCache ( {
60
+ h1 : {
61
+ keepAlive : false , // Default from `h1NoCache`.
62
+ family : 4
63
+ } ,
64
+ rejectUnauthorized : false // By default skip auth check for all.
65
+ } ) . fetch ;
66
+
67
+ function doFetch ( fetch_func , h1_fetch_func , h1_ipv4_fetch_func , options ) {
42
68
43
69
const fetch_options = Object . assign ( { } , options ) ;
44
70
@@ -56,7 +82,23 @@ function doFetch(fetch_func, h1_fetch_func, options) {
56
82
abortController . abort ( ) ;
57
83
} , options . timeout || CONFIG . RESPONSE_TIMEOUT ) ;
58
84
59
- const a_fetch_func = options . disable_http2 ? h1_fetch_func : fetch_func ;
85
+ var http2_used = false ;
86
+ var a_fetch_func ;
87
+
88
+ if ( options . use_ipv4 ) {
89
+
90
+ a_fetch_func = h1_ipv4_fetch_func ;
91
+
92
+ } else if ( options . disable_http2 ) {
93
+
94
+ a_fetch_func = h1_fetch_func ;
95
+
96
+ } else {
97
+
98
+ a_fetch_func = fetch_func ;
99
+ http2_used = true ;
100
+ }
101
+
60
102
return new Promise ( ( resolve , reject ) => {
61
103
a_fetch_func ( uri , fetch_options )
62
104
. then ( response => {
@@ -67,11 +109,11 @@ function doFetch(fetch_func, h1_fetch_func, options) {
67
109
} ) ;
68
110
abortController . onResponse ( stream ) ;
69
111
70
- if ( response . status !== 200 && ! options . disable_http2 && response . httpVersion === '2.0'
112
+ if ( response . status !== 200 && http2_used && response . httpVersion === '2.0'
71
113
&& CONFIG . DISABLE_HTTP2_CHECKS ?. some ( check => typeof check === 'function'
72
114
&& check ( response . status , headers ) ) ) {
73
115
log ( ' -- doFetch check disabled h2' , uri ) ;
74
- resolve ( doFetch ( fetch_func , h1_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
116
+ resolve ( doFetch ( fetch_func , h1_fetch_func , h1_ipv4_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
75
117
} else {
76
118
stream . status = response . status ;
77
119
if ( response . url && response . url !== uri ) { // Set as final destination url if Fetch follows 301/302 re-directs
@@ -85,25 +127,25 @@ function doFetch(fetch_func, h1_fetch_func, options) {
85
127
} )
86
128
. catch ( error => {
87
129
clearTimeout ( timeoutTimerId ) ;
88
- if ( ! options . disable_http2 && error . code && / ^ E R R _ H T T P 2 / . test ( error . code ) ) {
130
+ if ( http2_used && error . code && / ^ E R R _ H T T P 2 / . test ( error . code ) ) {
89
131
90
132
log ( ' -- doFetch http2 error' , error . code , uri ) ;
91
- resolve ( doFetch ( fetch_func , h1_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
133
+ resolve ( doFetch ( fetch_func , h1_fetch_func , h1_ipv4_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
92
134
93
- } else if ( ! options . disable_http2 && error . code && error instanceof FetchError && error . code === 'ABORT_ERR' ) {
135
+ } else if ( http2_used && error . code && error instanceof FetchError && error . code === 'ABORT_ERR' ) {
94
136
95
137
// Special case, when shared session request aborted by htmlparser logic.
96
138
/**
97
139
* https://polldaddy.com/poll/7451882/?s=twitter
98
140
* https://app.everviz.com/show/O0Cy7Dyt
99
141
*/
100
142
log ( ' -- doFetch h2 aborted error' , uri ) ;
101
- resolve ( doFetch ( fetch_func , h1_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
143
+ resolve ( doFetch ( fetch_func , h1_fetch_func , h1_ipv4_fetch_func , Object . assign ( { } , options , { disable_http2 : true } ) ) ) ;
102
144
103
145
} else if ( ! options . stopRecursion && CONFIG . ERRORS_TO_RETRY ?. some ( code => error . code ?. indexOf ( code ) > - 1 ) ) {
104
146
105
147
log ( ' -- doFetch ECONNRESET retry' , error . code , uri ) ;
106
- resolve ( doFetch ( fetch_func , h1_fetch_func , Object . assign ( { } , options , { stopRecursion : true , disable_http2 : true } ) ) ) ;
148
+ resolve ( doFetch ( fetch_func , h1_fetch_func , h1_ipv4_fetch_func , Object . assign ( { } , options , { stopRecursion : true , disable_http2 : true } ) ) ) ;
107
149
108
150
} else {
109
151
if ( error instanceof AbortError ) {
@@ -117,15 +159,15 @@ function doFetch(fetch_func, h1_fetch_func, options) {
117
159
}
118
160
119
161
export function fetchStreamKeepAlive ( options ) {
120
- return doFetch ( fetchKeepAlive , fetchH1KeepAlive , options ) ;
162
+ return doFetch ( fetchKeepAlive , fetchH1KeepAlive , fetchIPv4H1KeepAlive , options ) ;
121
163
}
122
164
123
165
export function fetchStream ( options ) {
124
- return doFetch ( fetch , fetchH1 , options ) ;
166
+ return doFetch ( fetch , fetchH1 , fetchIPv4H1 , options ) ;
125
167
} ;
126
168
127
169
export function fetchStreamAuthorized ( options ) {
128
- return doFetch ( fetchAuthorized , fetchH1Authorized , options ) ;
170
+ return doFetch ( fetchAuthorized , fetchH1Authorized , fetchIPv4H1Authorized , options ) ;
129
171
} ;
130
172
131
173
export function fetchData ( options ) {
@@ -144,7 +186,21 @@ export function fetchData(options) {
144
186
abortController . abort ( ) ;
145
187
} , options . timeout || CONFIG . RESPONSE_TIMEOUT ) ;
146
188
147
- const a_fetch_func = options . disable_http2 ? fetchH1 : fetch ;
189
+ var a_fetch_func ;
190
+
191
+ if ( options . use_ipv4 ) {
192
+
193
+ a_fetch_func = fetchIPv4H1 ;
194
+
195
+ } else if ( options . disable_http2 ) {
196
+
197
+ a_fetch_func = fetchH1 ;
198
+
199
+ } else {
200
+
201
+ a_fetch_func = fetch ;
202
+ }
203
+
148
204
return new Promise ( ( resolve , reject ) => {
149
205
a_fetch_func ( uri , fetch_options )
150
206
. then ( response => {
0 commit comments