0

I create some kind of "routing system" for RestfulAPI in function runUrl - on input I put url which contains some parameters (ID values) and I want to find this url in routes array, execute function given for that route with this parameters, and return that result as runUrl result.

function runUrl(url) {
  return projects('f505ecfb74','5e735f505c'); // hardcoded mockup
  // Question: how this function should look like ?
}


let routes = [
  ['/cars', cars ],
  ['/companies/:companyId/cars/:carId/projects', projects ],
  ['/companies/:companyId/room/:roomId', rooms ],
  //... 
];

// list of funtions to execute for given url

function cars() { return ["car1","car2"]; }

function projects(companyId,carId) { return [`proj-${companyId}`,`proj-${carId}`]; }

function rooms(companyId,roomId) { return `room-${companyId}-room-${roomId}` }

// ... (more functions)


// TEST
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'));

So far I write below function - but I have headache and it doesn't work

function runUrl(url) {
  let route = routes.find( r=> url.match(r[0]) );
  if(route) {
    return route[1](url.match(route[0]));
  }
  return null;
}

The parameters values are alpha-numeric strings, parameters names in routes array start with : and then are alpha-numeric strings too. The number of parameters is arbitrary.

How function runUrl should look like?

5
  • Is the routes array unchangeable, or can you modify it? Commented May 14, 2020 at 18:21
  • developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… expectes the argument given to it to be a regular expression. None of your r[0] values are regular expressions Commented May 14, 2020 at 18:21
  • @CertainPerformance rather unchangeable - but If you have some proposition to change it - fill free to show it Commented May 14, 2020 at 18:23
  • I'd put regular expressions in there instead, and for the first one that passes, call the appropriate function the matching parameters Commented May 14, 2020 at 18:24
  • @CertainPerformance - sorry, routes should be as simple as possible so putting regexp there are not allowed Commented May 14, 2020 at 18:25

2 Answers 2

1

I don't think you can do it with the match method because it's not meant to be equal between two strings, but I think I found an elegant solution to your problem, maybe it will help you :

let routes = [
  ['/cars', cars ],
  ['/companies/:companyId/cars/:carId/projects', projects ],
  ['/companies/:companyId/room/:roomId', rooms ],
];

function runUrl(url) {
  let arrUrl = url.split('/') // it will make an array with any value after /
  let route = routes.find( r=> arrUrl.length === r[0].split('/').length ); // it supposed to be equal by length
  if(route) {
    let params = arrUrl.filter(p => p && p.match(/\d+/)) // it will cut only the ids (string with number)
    return route[1](params);
  }
  return null;
}


// list of funtions to execute for given url

function cars() { 
  return ["car1","car2"];
}

function projects(array) { 
  return [`proj-${array[0]}`,`proj-${array[1]}`];
}

function rooms(array) {
  return `company-${array[0]}-room-${array[1]}`;
}

// ... (more functions)
  

// TEST
console.log(runUrl('/cars'))
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'))
console.log(runUrl('/companies/f505ecfb74/room/5e735f505c'))

Sign up to request clarification or add additional context in comments.

Comments

1

Here is my proposition, similar to tomer raitz idea but use regexp to detect parameters

function runUrl(url) {
    let result = undefined;
    let u = url.split("/");
    
    routes.find( ([route,func]) => {
        let r = route.split("/");
        if(r.length==u.length && r.every( (el,i) => /^:/.test(el) || el===u[i] ) ){
            let params = u.filter((el,i)=> /^:/.test(r[i]));
            result = func.call(this,...params);
            return true;
        }            
        return false;
    })  
    return result;      
}



// -----------
// TEST
// -----------

let routes = [
  ['/cars', cars ],
  ['/companies/:companyId/cars/:carId/projects', projects ],
  ['/companies/:companyId/room/:roomId', rooms ],
  //... 
];
function cars() { return ["car1","car2"]; }
function projects(companyId,carId) { return [`proj-${companyId}`,`proj-${carId}`]; }
function rooms(companyId,roomId) { return `room-${companyId}-room-${roomId}`; }


// TEST
console.log(runUrl('/companies/f505ecfb74/cars/5e735f505c/projects'));
console.log(runUrl('/cars'))
console.log(runUrl('/companies/ABC123/room/DEF5678'))

1 Comment

Thank for this post, actually, I succeeded add "API" style in a WebSocket connection request based on your idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.