JavaScript does URL checking, usually using regular expressions to determine whether the format is correct, for example:
Copy Code code as follows:
/^https?:\ /\//.test (URL);
Of course, there are better detection methods, such as RFC 3986, RFC 3966, RFC 4694, RFC 4759, RFC 4904, and other standard validation valid-url libraries.
But a validation based on the format is certainly not sure if the URL exists, so there is a url-valid, which we validate based on HTTP requests.
Interface Design
In fact, we just need a function to pass in a URL address and callback to return whether the link is available.
But the request is prone to an unknown error, so we pass an error parameter in the callback function, and if not NULL, there is an error.
We may also want to be able to get the relevant data on the Web page for future use in the information extraction of the page.
Chain operation as far as possible.
So the last thing to use is probably this:
Copy Code code as follows:
Valid (URL)
. On (' Check ', function (err, status) {
if (err) throw err;
Status?
Console.log (' URL is available '):
Console.log (' URL is not available ');
})
. On (' Data ', function (err, data) {
Console.log (data);
})
. On (' End ', function (err, data) {
Console.log (' End of request ');
})
HTTP GET or HTTP head
We wanted to use the HTTP head request to do this, because the heads request would only return header information, which would reduce the request time, but not all links would be supported by the boss request.
So finally we use the HTTP GET method to abort the request immediately after getting the correct statuscode.
processing 301-303
Since 301 to 303 are redirect States, we need to continue checking to see if the corresponding location still exists.
Asynchronous execution with Process.nexttick
In order to execute the code after registering for listening, we use Process.nexttick to do one step.
Realize
Copy Code code as follows:
/*!
* Valid
* MIT Licensed
*/
Module.exports = (function () {
' Use strict ';
var http = require (' http ')
, HTTPS = require (' HTTPS ')
, Eventemitter = require (' Events '). Eventemitter
, url = require (' URL ')
, Urlreg =/^ (https?): \ /\//;
/**
* Valid
* @class
*/
function Valid (URL, callback) {
var that = this;
This.url = URL;
This.emitter = new Eventemitter ();
Process.nexttick (function () {
That.get (URL);
});
This.fetch = false;
Callback && this.emitter.on (' Check ', callback);
}
Valid.prototype = {
Constructor:valid,
/**
* Get
* @param {String} URL
*/
Get:function (URL) {
var match = Url.match (Urlreg)
, that = this;
if (match) {
var httplib = (match[1].tolowercase () = = ' http ')? Http:https
, opts = Url.parse (URL)
, req;
Opts.agent = false;
Opts.method = ' get ';
req = Httplib.request (opts, function (res) {
var statusCode = Res.statuscode;
if (StatusCode = = 200) {
That.emitter.emit (' check ', NULL, true);
That.fetch?
(Res.on (' Data ', function (data) {
That.emitter.emit (' data ', null, data);
}) && Res.on (' End ', function () {
That.emitter.emit (' End ');
})) :
(Req.abort () | | | that.emitter.emit (' end '));
else if (< StatusCode && StatusCode < 304) {
Req.abort ();
var emitter = That.emitter
, valid = one (Url.resolve (URL, res.headers.location), function (err, valid) {
Emitter.emit (' Check ', err, valid);
});
That.fetch && valid.on (' Data ', function (err, data) {
Emitter.emit (' Data ', err, data);
});
Valid.on (' Error ', function (err) {
That.emitter.emit (' ERROR ', err);
});
Valid.on (' End ', function () {
That.emitter.emit (' End ');
});
} else {
That.emitter.emit (' check ', NULL, FALSE);
}
Res.on (' Error ', function (err) {
Req.abort ();
That.emitter.emit (' data ', err);
});
});
Req.on (' Error ', function (err) {
Req.abort ();
Return That.emitter.emit (' check ', NULL, FALSE);
});
Req.end ();
} else {
Return That.emitter.emit (' check ', NULL, FALSE);
}
},
/**
* On
* @param {STIRNG} event
* @param {Function} callback
*/
On:function (event, callback) {
(Event = = ' data ') && (This.fetch = true);
This.emitter.on (event, callback);
return this;
},
/**
* Destroy
*/
Destroy:function () {
This.emitter.removeAllListeners ();
This.url = undefined;
This.emitter = null;
This.fetch = undefined;
},
/**
* Removealllisteners
* @param
*/
Removealllisteners:function (event) {
Event?
This.emitter.removeAllListeners (Event):
This.emitter.removeAllListeners ();
return this;
},
/**
* Listeners
* @param
*/
Listeners:function (event) {
if (event) {
Return This.emitter.listeners (event);
} else {
var res = []
, that = this
, _push = Array.prototype.push;
Object.keys (this.emitter._events). ForEach (function (key) {
_push.apply (res, that.emitter.listeners (key));
});
return res;
}
}
}
/**
* One
* @param {String} URL
* @param {Function} callback
* @return {Valid}
*/
function one (URL, callback) {
Return (new Valid (URL, callback));
}
One.one = one;
return one;
})();