@@ -86,31 +86,59 @@ function waitTimeMs(ms) {
8686 } ) ;
8787}
8888
89- /**
90- * Create isAliveURI function with options
91- * @param {object } options
92- * @returns {isAliveURI }
93- */
94- const createCheckAliveURL = ( options ) => {
95- const keepAliveAgents = {
96- http : new http . Agent ( { keepAlive : true } ) ,
97- https : new https . Agent ( { keepAlive : true } ) ,
98- } ;
89+ const keepAliveAgents = {
90+ http : new http . Agent ( { keepAlive : true } ) ,
91+ https : new https . Agent ( { keepAlive : true } ) ,
92+ } ;
93+
94+ const createFetchWithRuleDefaults = ( ruleOptions ) => {
9995 /**
10096 * Use library agent, avoid to use global.http(s)Agent
10197 * Want to avoid Socket hang up
10298 * @param parsedURL
10399 * @returns {module:http.Agent|null|module:https.Agent }
104100 */
105101 const getAgent = ( parsedURL ) => {
106- if ( ! options . keepAlive ) {
102+ if ( ! ruleOptions . keepAlive ) {
107103 return null ;
108104 }
109105 if ( parsedURL . protocol === 'http:' ) {
110106 return keepAliveAgents . http ;
111107 }
112108 return keepAliveAgents . https ;
113109 } ;
110+
111+ return ( uri , fetchOptions ) => {
112+ const { host } = URL . parse ( uri ) ;
113+ return fetch ( uri , {
114+ ...fetchOptions ,
115+ // Disable gzip compression in Node.js
116+ // to avoid the zlib's "unexpected end of file" error
117+ // https://github.com/request/request/issues/2045
118+ compress : false ,
119+ // Some website require UserAgent and Accept header
120+ // to avoid ECONNRESET error
121+ // https://github.com/textlint-rule/textlint-rule-no-dead-link/issues/111
122+ headers : {
123+ 'User-Agent' : 'textlint-rule-no-dead-link/1.0' ,
124+ 'Accept' : '*/*' ,
125+ // Same host for target url
126+ // https://github.com/textlint-rule/textlint-rule-no-dead-link/issues/111
127+ 'Host' : host ,
128+ } ,
129+ // custom http(s).agent
130+ agent : getAgent ,
131+ } ) ;
132+ } ;
133+ } ;
134+ /**
135+ * Create isAliveURI function with ruleOptions
136+ * @param {object } ruleOptions
137+ * @returns {isAliveURI }
138+ */
139+ const createCheckAliveURL = ( ruleOptions ) => {
140+ // Create fetch function for this rule
141+ const fetchWithDefaults = createFetchWithRuleDefaults ( ruleOptions ) ;
114142 /**
115143 * Checks if a given URI is alive or not.
116144 *
@@ -127,39 +155,21 @@ const createCheckAliveURL = (options) => {
127155 * @return {{ ok: boolean, redirect?: string, message: string } }
128156 */
129157 return async function isAliveURI ( uri , method = 'HEAD' , maxRetryCount = 3 , currentRetryCount = 0 ) {
130- const { host } = URL . parse ( uri ) ;
131-
132158 const opts = {
133159 method,
134- // Disable gzip compression in Node.js
135- // to avoid the zlib's "unexpected end of file" error
136- // https://github.com/request/request/issues/2045
137- compress : false ,
138- // Some website require UserAgent and Accept header
139- // to avoid ECONNRESET error
140- // https://github.com/textlint-rule/textlint-rule-no-dead-link/issues/111
141- headers : {
142- 'User-Agent' : 'textlint-rule-no-dead-link/1.0' ,
143- 'Accept' : '*/*' ,
144- // Same host for target url
145- // https://github.com/textlint-rule/textlint-rule-no-dead-link/issues/111
146- 'Host' : host ,
147- } ,
148160 // Use `manual` redirect behaviour to get HTTP redirect status code
149161 // and see what kind of redirect is occurring
150162 redirect : 'manual' ,
151- // custom http(s).agent
152- agent : getAgent ,
153163 } ;
154164 try {
155- const res = await fetch ( uri , opts ) ;
156-
165+ const res = await fetchWithDefaults ( uri , opts ) ;
166+ // redirected
157167 if ( isRedirect ( res . status ) ) {
158- const finalRes = await fetch (
159- uri ,
160- Object . assign ( { } , opts , { redirect : 'follow' } ) ,
168+ const redirectedUrl = res . headers . get ( 'Location' ) ;
169+ const finalRes = await fetchWithDefaults (
170+ redirectedUrl ,
171+ { ...opts , redirect : 'follow' } ,
161172 ) ;
162-
163173 const { hash } = URL . parse ( uri ) ;
164174 return {
165175 ok : finalRes . ok ,
@@ -168,7 +178,7 @@ const createCheckAliveURL = (options) => {
168178 message : `${ res . status } ${ res . statusText } ` ,
169179 } ;
170180 }
171-
181+ // retry if it is not ok when use head request
172182 if ( ! res . ok && method === 'HEAD' && currentRetryCount < maxRetryCount ) {
173183 return isAliveURI ( uri , 'GET' , maxRetryCount , currentRetryCount + 1 ) ;
174184 }
@@ -222,8 +232,8 @@ async function isAliveLocalFile(filePath) {
222232function reporter ( context , options = { } ) {
223233 const { Syntax, getSource, report, RuleError, fixer, getFilePath } = context ;
224234 const helper = new RuleHelper ( context ) ;
225- const opts = Object . assign ( { } , DEFAULT_OPTIONS , options ) ;
226- const isAliveURI = createCheckAliveURL ( opts ) ;
235+ const ruleOptions = { ... DEFAULT_OPTIONS , ... options } ;
236+ const isAliveURI = createCheckAliveURL ( ruleOptions ) ;
227237 // 30sec memorized
228238 const memorizedIsAliveURI = pMemoize ( isAliveURI , {
229239 maxAge : 30 * 1000 ,
@@ -236,17 +246,17 @@ function reporter(context, options = {}) {
236246 * @param {number } maxRetryCount retry count of linting
237247 */
238248 const lint = async ( { node, uri, index } , maxRetryCount ) => {
239- if ( isIgnored ( uri , opts . ignore ) ) {
249+ if ( isIgnored ( uri , ruleOptions . ignore ) ) {
240250 return ;
241251 }
242252
243253 if ( isRelative ( uri ) ) {
244- if ( ! opts . checkRelative ) {
254+ if ( ! ruleOptions . checkRelative ) {
245255 return ;
246256 }
247257
248258 const filePath = getFilePath ( ) ;
249- const base = opts . baseURI || filePath ;
259+ const base = ruleOptions . baseURI || filePath ;
250260 if ( ! base ) {
251261 const message =
252262 'Unable to resolve the relative URI. Please check if the base URI is correctly specified.' ;
@@ -266,7 +276,7 @@ function reporter(context, options = {}) {
266276 }
267277
268278 const method =
269- opts . preferGET . filter (
279+ ruleOptions . preferGET . filter (
270280 ( origin ) => getURLOrigin ( uri ) === getURLOrigin ( origin ) ,
271281 ) . length > 0
272282 ? 'GET'
@@ -280,7 +290,7 @@ function reporter(context, options = {}) {
280290 if ( ! ok ) {
281291 const lintMessage = `${ uri } is dead. (${ message } )` ;
282292 report ( node , new RuleError ( lintMessage , { index } ) ) ;
283- } else if ( redirected && ! opts . ignoreRedirects ) {
293+ } else if ( redirected && ! ruleOptions . ignoreRedirects ) {
284294 const lintMessage = `${ uri } is redirected to ${ redirectTo } . (${ message } )` ;
285295 const fix = fixer . replaceTextRange (
286296 [ index , index + uri . length ] ,
@@ -341,11 +351,11 @@ function reporter(context, options = {}) {
341351
342352 [ `${ context . Syntax . Document } :exit` ] ( ) {
343353 const queue = new PQueue ( {
344- concurrency : opts . concurrency ,
345- intervalCap : opts . intervalCap ,
346- interval : opts . interval
354+ concurrency : ruleOptions . concurrency ,
355+ intervalCap : ruleOptions . intervalCap ,
356+ interval : ruleOptions . interval ,
347357 } ) ;
348- const linkTasks = URIs . map ( ( item ) => ( ) => lint ( item , opts . retry ) ) ;
358+ const linkTasks = URIs . map ( ( item ) => ( ) => lint ( item , ruleOptions . retry ) ) ;
349359 return queue . addAll ( linkTasks ) ;
350360 } ,
351361 } ;
0 commit comments