-1

I've created the example below to illustrate the desired outcome. Is it possible to do the same but against an array of URLPatterns?

// Example URL with two numerical params
const url = "https://example.com/app/api/v1/subscribers/1001/users/2001";

// Example URLPattern with two named groups
// https://web.dev/urlpattern/
// https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API
const urlPattern = new URLPattern({ pathname: "/app/api/v1/subscribers/:subscriberId/users/:userId" });

const urlValidate = urlPattern.test(url); // true
const urlExtract = urlPattern.exec(url); // { subscriberId: "1001", userId: "2001" }

// Debug
console.log("url:", url);
console.log("urlPattern:", urlPattern.pathname);
console.log("urlValidate:", urlValidate);
console.log("urlExtract:", urlExtract.pathname.groups);

// Cast subscriberId as Number
const subscriberId = Number(urlExtract.pathname.groups.subscriberId);
// Cast userId as Number
const userId = Number(urlExtract.pathname.groups.userId);

if(subscriberId && userId) console.log("Params validated for SQL Query.");

console.log("subscriberId:", subscriberId, "userId:", userId);
suchislife
  • 4,251
  • 10
  • 47
  • 78

2 Answers2

1

Are you trying to match the url with the patterns, and get the params from it? If so, you can try to do something like this:

const patterns = [
  new URLPattern({ pathname: "/app/api/v1/subscribers/:subscriberId/users/:userId" }),
  new URLPattern({ pathname: "/app/api/v1/users/:userId" }),
];

function getParams(url) {
  const pattern = patterns.find(p => p.test(url));
  if (pattern) {
    return pattern.exec(url).pathname.groups;
  }
}

const params = getParams('https://example.com/app/api/v1/subscribers/1001/users/2001');

if (params) {
  console.log(params); // { subscriberId: '1001', userId: '2001' }
} else {
  console.log('Invalid URL');
}
0

I was able to achieve it with RegEx but not URLPattern. Posting it here for completion.

const url = new URL("https://example.com/app/api/v1/subscribers/1001/users/2001");
const urlPathNameDecoded = decodeURIComponent(url.pathname);

const urlRegexPartsFound = validateGETurl(urlPathNameDecoded);

if(urlRegexPartsFound.length > 0) {
  // The end point matched by regex
  const endPointFound = urlRegexPartsFound[0];
  const subscriberId = urlRegexPartsFound[1];
  const userId = urlRegexPartsFound[2];

  console.log("subscriberId:", subscriberId, "userId:", userId);

} else {

  console.log("HTTP 404: Not Found")

}

function validateGETurl(urlPathNameDecoded) {

  // Local list of Method GET regular expressions to match against url pathname decoded
  const endPoints = [
    { endPoint: "/app/api/v1",                           regex: /^\/app\/api\/v1\/?$/ },
    { endPoint: "/app/api/v1/subscribers",               regex: /^\/app\/api\/v1\/subscribers\/?$/ },
    { endPoint: "/app/api/v1/subscribers/:id",           regex: /^\/app\/api\/v1\/subscribers\/([1-9]{1}[0-9]{0,8})\/?$/ },
    { endPoint: "/app/api/v1/subscribers/:id/users",     regex: /^\/app\/api\/v1\/subscribers\/([1-9]{1}[0-9]{0,8})\/users\/?$/ },
    { endPoint: "/app/api/v1/subscribers/:id/users/:id", regex: /^\/app\/api\/v1\/subscribers\/([1-9]{1}[0-9]{0,8})\/users\/([1-9]{1}[0-9]{0,8})\/?$/ },
    { endPoint: "/app/api/v1/help",                      regex: /^\/app\/api\/v1\/help\/?$/ },
  ];

  // Results of regex match may be stored in this array
  // If no match, this array remains empty at zero 0 length
  let urlRegexPartsFound = [];

  // Test if at least one element in the array passes the test implemented by the provided function
  endPoints.some(function(record) {

    // Execute regex against url pathname decoded
    const urlRegexMatchFound = record.regex.exec(urlPathNameDecoded);

    if(!urlRegexMatchFound) return;

    // if a match is found, populate urlRegexPartsFound with it
    if(urlRegexMatchFound) {
      // removes the first element from an array. redundant in this case.
      urlRegexMatchFound.shift();
      // re-construct array with name of end point & parts found
      urlRegexPartsFound = [record.endPoint, ...urlRegexMatchFound];
    }

  });

  return urlRegexPartsFound;

}
suchislife
  • 4,251
  • 10
  • 47
  • 78