Jax-RS overloading methods / execution paths

I am writing an API for my application and I am confused that Jax-RS deals with certain scenarios

For example, I define two paths:

@Path("user/{name : [a-zA-Z]+}")

      

and

@Path("user/me")

      

The first path I specified explicitly covers the second path, since the regex includes all the letters az. However, the program doesn't seem to have a problem with this. Is it because it defaults to the most specific path (i.e. / Me and then look for a regex)?

Also, what happens if I define two regexes as a path with some overlap. Is there a default method that will be called?

Let's say I want to create three paths for three different methods:

@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me")

      

Is this best practice / appropriate? How does it know which method to call?

Thanks in advance for any clarification.

+3


source to share


1 answer


This is the specification under Resource Query Matching

Sorting E

using (1) the number of alphabetic characters in each member as the primary key (descending order), (2) the number of captured groups as the secondary key (descending), (3) the number of captured groups with non-standard regexes (i.e. . not '([^ /] +?)) as a tertiary key (descending), ...

What happens is the candidate methods are sorted by the specified ordered "key". I mark them in bold.

The first sort key is the number of alphabetic characters. So, for these three

@Path{"user/{name : [a-zA-Z]+}")
@Path("user/{id : \\d+}")
@Path("user/me") 

      

if the requested URI is equal ../user/me

, the latter will always be selected since it has the most literal characters (7, /

counts). The rest have only 5.

Besides ../users/me

everything else ../users/..

will depend on the regular expression. In your case, one matches only numbers and one only matches letters. There is no way for these two regular expressions to overlap. So it will fit accordingly.



Now just for fun, let's say we have

@Path{"user/{name : .*}")
@Path("user/{id : \\d+}")
@Path("user/me")

      

If you look at the top two, we now have overlapping regular expressions. The first will match all numbers, just like the second. So which one will be used? We cannot make any assumptions. This is an undefined level of uncertainty, and I've seen different behavior from different implementations. AFAIK, there is no concept of "best match" regex. Either it matches or it doesn't.

But what if we want to {id : \\d+}

always check first. If it matches the numbers, this should be selected. We can crack it based on the spec. The spec talks about "capturing groups", which are basically {..}

s. The second sort key is the number of capture groups. The way we could hack it is to add another "optional" group

@Path{"user/{name : .*}")
@Path("user/{id : \\d+}{dummy: (/)?}")

      

The latter now has more capture groups, so he will always be in front. All it does is allow the optional /

, which doesn't really affect the API, but makes sure that if the request URI is all numbers, that path will always be chosen.

In this answer you can see a discussion with some test cases

+7


source







All Articles