0

I am developing a general function inside a solution which would replace /endpoint/{item.id}/disable/{item.name} with /endpoint/123/disable/lorem where I pass the function the URL and item.

The item would be an object with keys id and name.

What would be the best way to find items with the structure {item.KEY} and replacing them with item.KEY?

Anže Jenšterle
  • 73
  • 1
  • 2
  • 11

2 Answers2

2

the best way to solve this is passing a function to handle a regex. I modified your parameters to make the mapping easier- I'm sure you can change this on your own if necessary

var url = '/endpoint/{id}/disable/{name}'; //I modified your parameters

var definition = { id: 123, name: 'lorem' };
url = url.replace(/{([^}]*)}/g, function (prop) {
  var key = prop.substr(1, prop.length - 2);
  if (definition[key])
    return encodeURIComponent(definition[key]);
  else
    throw new Error('missing required property "' + key + '" in property collection');
});

//alert(url);

fiddle: https://jsfiddle.net/wovr4ct5/2/

Wolfgang
  • 876
  • 5
  • 13
  • Thank you, that was exactly what I was looking for. – Anže Jenšterle Jul 29 '16 at 13:05
  • Should I use definition[key] or definition.hasOwnProperty(key) for the if? – Anže Jenšterle Aug 05 '16 at 19:55
  • @AnžeJenšterle this depends on your "definition" object. If definition is an instance of a class, has properties defined using Object.defineProperties or is derived from another class you should used hasOwnProperty but in this case it doesn't make any difference – Wolfgang Aug 07 '16 at 11:48
1

If you don't want to use eval, maybe use something like this:

var item = {
    id: 123,
    KEY: "lorem"
};

function pick(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

and then

str.replace(/{.*?}/g, function(match){ // match {...}
    var path = match.substring(1,match.length-1); // get rid of brackets.
    return pick(scope, path); //get value and replace it in string.
});
Community
  • 1
  • 1
Krzysztof Atłasik
  • 21,985
  • 6
  • 54
  • 76
  • This seems like **exactly** the kind of situation where using `eval` would be super-dangerous. Good chance that wherever these strings are coming from, they haven't been sanitized. – A. Vidor Jul 29 '16 at 11:06
  • A much safer solution would be to supply `path.split('.')[1]` as a key to the `item` object. :) Will change down-vote to up-vote if you avoid `eval` in your solution. – A. Vidor Jul 29 '16 at 11:07
  • It is not clear what `pick` is supposed to accomplish. You're returning a reference to the global context? What is happening! `path` is already a string of the format `item.key`. How does `pick` improve on the single line in my previous comment? – A. Vidor Jul 29 '16 at 12:28
  • Oh, I see, you just copy-pasted from the linked solution. Sorry, but that's serious overkill. Down-vote remains, because you are still advocating `eval` in a (probably) unsafe context. – A. Vidor Jul 29 '16 at 12:30
  • Also, maybe you misunderstand the code you've pasted? What makes you think this string-based lookup should be performed on `window`? – A. Vidor Jul 29 '16 at 12:33
  • Ok, another attemp :) Scope is object holding "item" object. If this is global scope, then scope is window. – Krzysztof Atłasik Jul 29 '16 at 12:57
  • Again, while I appreciate your effort to give the general solution, the use of `eval` here could pose a real security risk to OP, and I would never promote it. As long as that remains the primary solution offered in this post, I can't up-vote it. – A. Vidor Jul 29 '16 at 15:34
  • Can you give example how it might be dangerous? On the client side? – Krzysztof Atłasik Jul 29 '16 at 19:40
  • It really depends on where that template string is coming from. OP hasn't told us. Your original code searched for a sub-string between curly-braces, then blindly executed it. If the content between curly-braces can be manipulated by a 3rd party (again, we don't know), any information available to the application scope becomes available to an attacker. For all we know, that string is being read from an un-signed, un-authenticated cookie served over HTTP! Since playing it safe only requires 10 more characters than the `eval` version, it'd be crazy to open that vulnerability. – A. Vidor Jul 29 '16 at 20:12