Search code examples
jakarta-eejax-wsresteasy

Replace path parameter dynamically


I have a @Provider which should replace a path variable like this:

@Provider
@Priority(value = 1)
public class SecurityCheckRequestFilter implements ContainerRequestFilter
{
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException
    {
        //CODE

        requestContext.getUriInfo().getPathParameters().putSingle("userId", someNewUserId);
    }
}

When I debug it, the path variable "userId" seems to be replaced, but at the endpoint later in the workflow (for example /user/{userId}), the old value appears again. Nothing was replaced. No information about this behaviour in the latest RestEasy doc, but in a very old Resteasy doc, there is an information, that getPathParameters() returns an unmodifiable list. If it is unmodifiable, why can I replace the value within the provider then? Nevertheless, the value is not replaced. How can I overwrite an existing path parameter with a new value?

(Sure, I could add the new userId as some header parameter and fetch the information later in the endpoint, but that's not a good solution)


Solution

  • I have a solution now. It's a little bit cumbersome but it works. First of all, I had to add an additional annotation @PreMatching. This causes the provider to be executed much earlier in request, so you can manipulate the path before it will be processed. The disadvantage is that I was not able to use PathParameters anymore, because the placeholder {userId} was not set at this time. Instead I had to somehow extract the information from the path by path segments:

    List<PathSegment> pathSegments = requestContext.getUriInfo().getPathSegments();

    Unfortunately, I had the rebuild the whole path from new (including the query parameters!) to change the userId.

    String fullPath = requestContext.getUriInfo().getPath();
    MultivaluedMap<String, String> queryParameters = requestContext.getUriInfo().getQueryParameters(true);
    
    String modifiedPath = fullPath.replaceFirst(obfuscationId, userId); 
    
    UriBuilder uriBuilder = UriBuilder.fromPath(modifiedPath);
    queryParameters.forEach((k,v) -> { uriBuilder.queryParam(k, v.get(0)); } );
    requestContext.setRequestUri(uriBuilder.build());