Home  >  Article  >  Web Front-end  >  How to use NodeJS url verification (url-valid)_Basic knowledge

How to use NodeJS url verification (url-valid)_Basic knowledge

WBOY
WBOYOriginal
2016-05-16 17:14:441178browse

Javascript usually uses regular expressions to check URLs to determine whether the format is correct, for example:

Copy code The code is as follows:

/^https?:///.test(url);

Of course there are better detection methods such as based on RFC 3986, RFC 3966, RFC 4694 , RFC 4759, RFC 4904 and other standard valid-url libraries for verification.
Of course, verification based on the format cannot determine whether the url exists, so with url-valid, we verify based on HTTP requests.

Interface design
In fact, we only need a function to pass in a url address, and callback to return whether the link is available.
But requests are prone to unknown errors, so we pass in an error parameter in the callback function. If it is not empty, an error occurs.
We may also hope to obtain relevant data of the web page and use it to extract information from the page in the future.
Chain operations as much as possible.
So the final usage is probably like this:
Copy the code The code is 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('Request ended');
})

HTTP GET Or HTTP HEAD
Originally we wanted to use HTTP HEAD request to achieve this, because HEAD request will only return header information, which can reduce the request time, but HEAD request may not be supported by all links.
So in the end we use the HTTP GET method and abort the request immediately after getting the correct statusCode.

Processing 301-303
Because 301 to 303 are redirect states, we need to continue to check whether the corresponding Location still exists.

Use process.nextTick to execute asynchronously
In order to execute the code after registering the listener, we use process.nextTick to perform a one-step operation.

Implementation
Copy code The code is 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 (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} 이벤트
     * @param {Function} 콜백
    */
    on: 함수(이벤트, 콜백) {
      (이벤트 === '데이터') && (this.fetch = true);
      this.emitter.on(event, callback);
      return this;
    },
    /**
     * 파괴
    */
    destroy: function () {
      this. Emitter.removeAllListeners();
      this.url = undefine;
      this.emitter = null;
      this.fetch = undefine;
    },
    /**
     * RemoveAllListeners
     * @param
    */
    RemoveAllListeners: 함수(이벤트) {
      이벤트 ?
        this.emitter.removeAllListeners(event) :
        this.emitter.removeAllListeners();
      return this;
    },
    /**
     * 청취자
     * @param
    */
    청취자: 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;
      }
    }
  }
  /**
   * 하나
   * @param {String} url
   * @param {함수} 콜백
   * @return {유효}
  */
  함수 1(url, 콜백) {
    return ( new Valid(url, 콜백));
  }
  one.one = one;
  하나 반환;
})();
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn