jfromaniello / express-unless

Conditionally add a middleware to express with some common patterns
MIT License
178 stars 27 forks source link

can't use unless for req.params #12

Open imakshath opened 8 years ago

imakshath commented 8 years ago

Hi,

I have the requirement to unless the endpoint url as below,

/api/sample/:type

here 'type' is the request param. The problem is that i can't unless the url . Its still showing unauthorized. So what is the solution for this?

imakshath commented 8 years ago

Hi Admin,

I have made some changes in index.js for fixing this issue. the changed index.js file looks as below,

var URL = require('url');
var UrlPattern = require('url-pattern');

module.exports = function (options) {
  var parent = this;

  var opts = typeof options === 'function' ? {custom: options} : options;
  opts.useOriginalUrl = (typeof opts.useOriginalUrl === 'undefined') ? true : opts.useOriginalUrl;

  return function (req, res, next) {
    var url = URL.parse((opts.useOriginalUrl ? req.originalUrl : req.url) || req.url || '', true);

    var skip = false;

    if (opts.custom) {
      skip = skip || opts.custom(req);
    }

    var paths = !opts.path || Array.isArray(opts.path) ?
                opts.path : [opts.path];

    if (paths) {
      skip = skip || paths.some(function (p) {
        return isUrlMatch(p, url.pathname) && isMethodMatch(p.methods, req.method);
      });
    }

    var exts = (!opts.ext || Array.isArray(opts.ext)) ?
               opts.ext : [opts.ext];

    if (exts) {
      skip = skip || exts.some(function (ext) {
        return url.pathname.substr(ext.length * -1) === ext;
      });
    }

    var methods = (!opts.method || Array.isArray(opts.method)) ?
                  opts.method : [opts.method];

    if (methods) {
      skip = skip || !!~methods.indexOf(req.method);
    }

    if (skip) {
      return next();
    }

    parent(req, res, next);
  };
};

function isUrlMatch(p, url) {
  var pattern = new UrlPattern(p);
  var ret = (typeof p === 'string' && p === url) || (p instanceof RegExp && !!p.exec(url)) || (typeof p === 'string' && pattern.match(url) != null);
  if (p instanceof RegExp) {
    p.lastIndex = 0;
  }

  if (p && p.url) {
    ret = isUrlMatch(p.url, url)
  }
  return ret;
}

function isMethodMatch(methods, m) {
  if (!methods) {
    return true;
  }

  methods = Array.isArray(methods) ? methods : [methods];

  return !!~methods.indexOf(m);
}

I have injected url-pattern npm module for tracking the url and as well as updated the isUrlMatch() function for comparing the url with the array. Now its working fine for me.

flarocca commented 8 years ago

Hi akshath4u, i think i'm faceing the same problem but what i need now is to be able to pass as a url parameter a jwt token, for example i need to be able to do this:

http://localhost:8080/setNewPassword/**eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImZhY3VuZG9fbGFyb2NjYUB5YWhvby5jb20uYXIiLCJpYXQiOjE0NzYxMjgxNTZ9.uaLidLZ2eQLSa5ppW7N3z61xUHj5kSyTUUc8Q9nN_KY**

GET http://localhost:8080/setNewPassword/:token

Have you got any idea how to solve this?

Thanks a lot.