Route Matcher in JavaScript
This challenge asks you to implement a route matcher in JavaScript. A route matcher takes a URL path and a set of defined routes and determines if the URL path matches any of the routes. This is a fundamental component in web frameworks and APIs for routing requests to the correct handlers.
Problem Description
You need to create a function matchRoute(url, routes) that takes a URL path (string) and an array of route definitions as input. Each route definition is an object with a path property (string) and an optional method property (string). The function should return the first matching route object if a match is found, otherwise it should return null.
A route matches if:
- The URL path starts with the route's
path. - If a
methodis specified in the route, the request method (obtained from the URL - assumed to be the HTTP method, e.g., "GET", "POST") must match the route'smethod. For simplicity, assume the URL is always in the format[method] [path]. Extract the method by splitting the URL string by a space. - If no
methodis specified, any method is considered a match.
The matching should be based on prefix matching. For example, if the route path is /users, it should match /users, /users/123, and /users/profile.
Edge Cases to Consider:
- Empty URL or routes array.
- Route paths starting with a wildcard character (e.g.,
*). Wildcards should match any subsequent path segment. (This is an optional extension - see Notes). - Routes with empty paths.
- Case sensitivity of the URL path and route paths. (Assume case-sensitive matching for this challenge).
- Invalid URL format (no space separating method and path).
Examples
Example 1:
Input: url = "GET /users", routes = [{ path: "/users" }, { path: "/products", method: "POST" }]
Output: { path: "/users" }
Explanation: The URL path "/users" matches the first route's path. The method "GET" doesn't matter since the route doesn't specify a method.
Example 2:
Input: url = "POST /products", routes = [{ path: "/users" }, { path: "/products", method: "POST" }]
Output: { path: "/products", method: "POST" }
Explanation: The URL path "/products" matches the second route's path, and the method "POST" matches the route's specified method.
Example 3:
Input: url = "GET /users/123", routes = [{ path: "/users" }, { path: "/products", method: "POST" }]
Output: { path: "/users" }
Explanation: The URL path "/users/123" is a child path of "/users". The first matching route is returned.
Example 4:
Input: url = "GET /", routes = [{ path: "/users" }, { path: "/" }]
Output: { path: "/" }
Explanation: The URL path "/" matches the second route's path.
Constraints
urlwill be a string.routeswill be an array of objects.- Each route object will have a
pathproperty (string). - Each route object may have a
methodproperty (string). - The length of the
routesarray will be between 0 and 100. - The length of the
urlstring will be between 0 and 200. - The
methodin the URL and route (if present) will be a string of length between 1 and 10. - Route paths will be strings of length between 1 and 50.
- Performance: The function should ideally complete within 100ms for a typical input.
Notes
- Consider using string methods like
startsWith()for efficient prefix matching. - You can assume the URL is always in the format
[method] [path]. - This challenge focuses on the core matching logic. Error handling for invalid URLs is not required.
- Optional Extension (for extra challenge): Implement wildcard support in route paths. For example, a route with
path: "/users/*"should match/users,/users/123, and/users/profile. The*should match any sequence of characters. You'll need to handle this in your matching logic. - Think about how to handle the case where multiple routes match. The problem statement specifies returning the first matching route.
- Focus on clarity and readability of your code. Well-structured code is easier to understand and maintain.