NodeJS url验证(url-valid)的使用方法 |
本文标签:url验证 Javascript做url检验,通常是使用正则表达式来判定,其格式是否正确,例如: 复制代码 代码如下: /^https?:\/\//.test(url); 当然还有更好的检测方法比如基于RFC 3986, RFC 3966, RFC 4694, RFC 4759, RFC 4904等标准的进行验证的valid-url库 。 不过个根据格式进行验证当然不能确定该url是否存在啦,所以就有了url-valid,我们基于HTTP请求进行验证 。 接口设计 实际上我们只需要一个函数传入一个url地址,并回调返回该链接是否可用 。 但请求容易产生未知错误,所以我们在回调函数传入一个error参数,如果不为空,则有错误产生 。 我们可能还希望能够得到网页的相关数据,未来用在页面的信息提取上 。 尽可能链式操作吧 。 所以最后使用上大概是这样的: 复制代码 代码如下: valid(url) .on(check, function (err, status) { if (err) throw err; status ? console.log(url是可用的) : console.log(url是不可用的); }) .on(data, function (err, data) { console.log(data); }) .on(end, function (err, data) { console.log(请求结束); }) HTTP GET 还是 HTTP HEAD 本来我们想利用HTTP HEAD请求来实现的,因为HEAD请求只会返回头信息,这可以减少请求时间,但是HEAD请求,不一定所有链接都会支持 。 所以最后我们使用HTTP GET方式,在得到正确的statusCode后立刻abort掉请求 。 处理301-303 因为301到303都是重定向状态所以,我们需要继续检查对应Location是否依然存在 。 利用process.nextTick异步执行 为了在注册监听后,再执行代码,我们使用process.nextTick来一步操作 。 实现 复制代码 代码如下: /*! * 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 (300 < 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; })(); |