suchislife
suchislife

Reputation: 1

Validated URL against an Array of URLPatterns. How?

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);

Upvotes: -1

Views: 95

Answers (2)

suchislife
suchislife

Reputation: 1

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;

}

Upvotes: 0

Nanang Mahdaen El-Agung
Nanang Mahdaen El-Agung

Reputation: 1434

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');
}

Upvotes: 1

Related Questions