users@jax-rs-spec.java.net

[jax-rs-spec users] Re: Getting full path template after sub-resource locators

From: Ron Dagostino <rndgstn_at_gmail.com>
Date: Mon, 18 Apr 2016 10:34:31 -0400

Unfortunate. Thank you for reviewing it.

On Mon, Apr 18, 2016 at 10:08 AM, Marek Potociar <marek.potociar_at_oracle.com>
wrote:

> Hi Ron,
>
> I have reviewed this use case and I am afraid it is too narrow-scoped to
> justify change in the API. We have not seen any other similar requests so
> far to support the justification behind your use case.
>
> Kind regards,
> Marek
>
> On 17 Feb 2016, at 16:50, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>
> Thanks for the feedback, Marek. Here is our use case.
>
> We annotate our resource methods with @RolesAllowed to identify the roles
> that can invoke them. The listed roles correspond to role names in our
> role-based access control repository (RBAC), and we make the authz decision
> in a post-match ContainerRequestFilter. The filter verifies an incoming
> signed OAuth bearer token and extracts the set of active roles in the token
> from a claim. The filter then decides to accept or reject the request
> based on whether or not there is an intersection between the active roles
> in the token claim and the roles listed in the @RolesAllowed annotation.
> This works great, but we have an audit/compliance requirement to be able to
> clearly identify which roles are allowed to invoke which APIs, and we are
> now deciding how to meet this requirement. Our thought is that the APIs
> can be identified at runtime by their method and full template path. For
> example:
>
> We would be able to identify at runtime the following two facts:
>
>
> FooRole is able to invoke "GET root/foo={value}"
> IdsRole is able to invoke "GET root/id1={id1Value}/id2={id2Value}"
>
>
> If we have these code definitions:
>
>
> @Path("root") // resource class
> public class Root {
> @Path("foo={value}") // sub-resource method
> @RolesAllowed("FooRole") // token/RBAC authnz
> public String get() {
> return "foo";
> }
>
> @Path("id1={id1Value}") // sub-resource locator
> public SubResource getSubResource() {
> return new SubResource();
> }
> }
>
> public class SubResource {
> @Path("id2={id2Value}")
> @GET // sub-resource method
> @RolesAllowed("IdsRole") // token/RBAC authz
> public String get() {
> return "ids";
> }
> }
>
>
> It makes sense to report the full template path rather than the URL
> because every URL is different (root/foo=1, root/foo=abc, etc.) but the
> full template path is the same for every matching URL (root/foo={value}).
>
> The current 2.0 API does not support (easily, without re-implementing
> stage 3 of the matching algorithm) identifying the full path template when
> sub-resource locators are involved.
>
> Using the full path template is not the only approach. We could require
> the use of an additional annotation to explicitly provide an API method
> identifier, or we could use java.lang.reflect.Method.toGenericString() to
> identify the API method name. So there are workarounds. But the best
> solution to us at this time seems to be to always report something of the
> form "<HTTPMETHOD> <full/{template}/path>" -- it is API-friendly because
> everybody thinks in terms of methods and paths, and the information is
> there already; we are just looking for an API to get at it.
>
> Is this something a lot of people would want to do? I don't know. There
> was a reason for including UriInfo.getMatchingResources() and
> UriInfo.getPathParameters(); I don't know what the reason was, but the
> use case I describe requires a more complete exposure of the kind of
> information that these methods already provide.
>
> Ron
>
>
>
> On Wed, Feb 17, 2016 at 10:01 AM, Marek Potociar <
> marek.potociar_at_oracle.com> wrote:
>
>> Hi Ron,
>>
>> I think you really need to first make case why is it important to expose
>> API for constructing a full path template. We need to understand how many
>> people would benefit from such API, before we can consider adding it to the
>> spec.
>>
>> Cheers,
>> Marek
>>
>> On 17 Feb 2016, at 03:01, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>
>> Hi again. I have concluded that it is not possible to construct the full
>> path template for a request without (re-)implementing a significant portion
>> of the matching algorithm (specifically, stage 3). The problem is that
>> UriInfo does not provide a complete picture of what happened during the
>> matching process -- it does not specify which methods were matched on
>> instances generated by sub-resource locators. It provides the instances,
>> but it does not provide the matched methods.
>>
>> Assuming it is agreed to be reasonable to want to know the full path
>> template for a request (I can explain why I want to do this if necessary),
>> and assuming I am not missing anything and it is indeed not (easily)
>> possible with the 2.0 API, and simple solution would be to add a method to
>> UriInfo that returns the matched methods as shown in the sample Javadoc
>> below. A more complete solution would be to expose the entire match model:
>> a list with each element being an object that contained a resource method,
>> a path parameters map (empty if no template substitutions were made), and
>> the matched resource.
>>
>> I am hoping for some feedback on this.
>>
>> Ron
>>
>> java.lang.List<java.lang.reflect.Method> *getMatchedMethods*()
>>
>> Get a read-only list of the currently matched resource methods. Each
>> entry is a resource method that matched the request URI either directly or
>> via a sub-resource method or a sub-resource locator. Entries are ordered
>> according to reverse request URI matching order, with the current resource
>> method first. E.g. given the following resource classes:
>>
>> @Path("foo")
>> public class FooResource {
>> @GET
>> public String getFoo() {...}
>>
>> @Path("bar")
>> public BarResource getBarResource() {...}
>> }
>>
>> public class BarResource {
>> @GET
>> public String getBar() {...}
>> }
>>
>>
>> The values returned by this method based on request uri and where the
>> method is called from are:
>> RequestCalled fromValue(s)
>> GET /foo FooResource.getFoo FooResource.getFoo
>> GET /foo/bar FooResource.getBarResource FooResource.getBarResource
>> GET /foo/bar BarResource.getBar BarResource.getBar,
>> FooResource.getBarResource
>>
>> RequestCalled fromValue(s)
>> GET /foo RequestContextFilter (pre-match) null
>> GET /foo
>> RequestContextFilter (post-match)
>> FooResource.getFoo
>> GET /foo/bar
>> RequestContextFilter (post-match)
>> BarResource.getBar, FooResource.getBarResource
>>
>> *Returns:*a read-only list of matched resource methods.
>>
>>
>>
>> On Mon, Feb 15, 2016 at 9:55 PM, Ron Dagostino <rndgstn_at_gmail.com> wrote:
>>
>>> Hi everyone. I want to write a ContainerRequestFilter that can generate
>>> the full path template value "root/id1={id1Value}/id2={id2Value}" for the
>>> following case and also generate correct full path template values in the
>>> general case. I don't think it can be reliably done when sub-resource
>>> locators are involved. For example, given these classes:
>>>
>>>
>>> @Path("root") // resource class
>>> public class Root {
>>> @Path("id1={id1Value}") // sub-resource locator
>>> public SubResource getSubResource() {
>>> return new SubResource();
>>> }
>>> }
>>>
>>> public class SubResource {
>>> @Path("id2={id2Value}")
>>> @GET // sub-resource method
>>> public String get() {
>>> return "the entity";
>>> }
>>> }
>>>
>>> And given this request:
>>>
>>> /root/id1=2/id2=2
>>>
>>>
>>> The problem is that uriInfo.getPathParameters() returns this
>>> MultiValuedMap in the filter:
>>>
>>> {id2Value=[2], id1Value=[2]}
>>>
>>> There is no way I can reliably get from "/root/id1=2/id2=2" to
>>> "root/id1={id1Value}/id2={id2Value}" given the MultiValuesMap contents.
>>>
>>> Basically I think there is no way to reliably know what the full path
>>> template value is for a request when sub-resource locators are involved.
>>> Is this true?
>>>
>>> Ron
>>>
>>
>>
>>
>
>