在 quarkus 过滤器中添加请求查询参数
Add request query params in quarkus filter
我有一个 url 喜欢 http://localhost:8080?scope=openid%20profile
我要转给http://localhost:8080?scope=openid&scope=profile
以便以下端点可以接受它。
// 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) {
...
}
我尝试添加如下过滤器,但请求参数映射 不可修改 !
// 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));
}
}
}
那么有没有合适的方法来修改过滤器或其他拦截器中的请求参数?
我还尝试使 Set<Scope>
成为一个 class,它接收一个 String
值作为构造函数参数,
但是如何获得将 String
值转换为 Scope
实例而不是调用 Scope.fromString
的转换器?
我认为您不能为此使用过滤器,正是因为不允许过滤器更改参数。您可以使用参数转换器,大致如下所示:
@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
}
}
我有一个 url 喜欢 http://localhost:8080?scope=openid%20profile
我要转给http://localhost:8080?scope=openid&scope=profile
以便以下端点可以接受它。
// 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) {
...
}
我尝试添加如下过滤器,但请求参数映射 不可修改 !
// 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));
}
}
}
那么有没有合适的方法来修改过滤器或其他拦截器中的请求参数?
我还尝试使 Set<Scope>
成为一个 class,它接收一个 String
值作为构造函数参数,
但是如何获得将 String
值转换为 Scope
实例而不是调用 Scope.fromString
的转换器?
我认为您不能为此使用过滤器,正是因为不允许过滤器更改参数。您可以使用参数转换器,大致如下所示:
@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
}
}