Reputation: 1
I've created the example below to illustrate the desired outcome. Is it possible to do the same but against an array of URLPattern
s?
// 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
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
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