'Add request query params in quarkus filter
I have a url like http://localhost:8080?scope=openid%20profile
I want to transfer it to http://localhost:8080?scope=openid&scope=profile
so that the following endpoint could accept it.
// Scope.java
public enum Scope {
OPENID,
PROFILE;
public static Scope fromString(String value) {
return valueOf(value.toUpperCase());
}
}
// AuthorizationEndpoint.java
@GET
@Path("authorize")
public Response authorize(@Valid @NotEmpty @QueryParam("scope") Set<Scope> scope) {
...
}
I tried to add a filter like below, but the map of request params is unmodifiable !
// Split.java
public @interface Split {
String value();
}
// AuthorizationEndpoint.java
@GET
@Path("authorize")
// add @Split(" ")
public Response authorize(@Valid @NotEmpty @QueryParam("scope") @Split(" ") Set<Scope> scope)
{
...
}
// SplitFilter.java
@Provider
class SplitFilter implements ContainerRequestFilter {
private final ResourceInfo resourceInfo;
SplitFilter(ResourceInfo resourceInfo) {
this.resourceInfo = resourceInfo;
}
@Override
public void filter(ContainerRequestContext requestContext) {
for (var parameter: resourceInfo.getResourceMethod().getParameters()) {
var queryParam = parameter.getAnnotation(QueryParam.class);
if (queryParam == null) continue;
var split = parameter.getAnnotation(Split.class);
if (split == null) continue;
var queryName = queryParam.value();
// Note: queryParams is unmodifiable!!!
var queryParams = requestContext.getUriInfo().getQueryParameters();
var originQueryValues = queryParams.get(queryName);
if (originQueryValues.size() != 1) {
throw new IllegalStateException("Incorrect size of query values: " + originQueryValues + ", expect only 1.");
}
var splitQueryValue = originQueryValues.get(0).split(split.value());
// Error: originQueryValues is unmodifiable!!!
originQueryValues.clear();
originQueryValues.addAll(Arrays.asList(splitQueryValue));
}
}
}
So is there a proper way to modify the request params in filters or other inteceptors?
I also tried to make Set<Scope> a single class that recieves a String value as constructor param,
but how to get the converter that converts a String value to a instance of Scope instead of calling Scope.fromString?
Solution 1:[1]
I think you can't use a filter for that, exactly because a filter is not allowed to change the params. You could use a param converter, roughly something like this:
@Provider
public class ScopeConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if(rawType == Set.class) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(Split.class)) {
return (ParamConverter<T>) new ScopeConverter(((Split) annotation).value());
}
}
return (ParamConverter<T>) new ScopeConverter(" ");// default if there's no @Split annotation
}
return null;
}
}
public class ScopeConverter implements ParamConverter<Set<Scope>> {
private final String splitCharacter;
public ScopeConverter(String splitCharacter) {
this.splitCharacter = splitCharacter;
}
@Override
public Set<Scope> fromString(String value) {
// strip the [] that the value gets automatically wrapped in,
// because the query param is a set
value = value.substring(1, value.length() - 1);
String[] splits = value.split(splitCharacter);
HashSet<Scope> scopes = new HashSet<>();
for (String split : splits) {
scopes.add(Scope.fromString(split));
}
return scopes;
}
@Override
public String toString(Set<Scope> value) {
return null; // unused
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jan Martiška |
