【发布时间】:2021-09-03 15:43:30
【问题描述】:
我相信我正在使用 Jersey 客户端 2.29。
在处理请求时,服务器会以Content-Type = application/ 响应(当然这是一个虚假值,它应该是application/json)。 jersey 炸了,因为它无法解析媒体类型的子类型:
java.util.concurrent.CompletionException: org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/"
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1702)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:314)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:309)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:422)
at com.test.web.ext.filter.LoggingFilter.filter(LoggingFilter.java:94)
at org.glassfish.jersey.client.ClientFilteringStages$ResponseFilterStage.apply(ClientFilteringStages.java:109)
at org.glassfish.jersey.client.ClientFilteringStages$ResponseFilterStage.apply(ClientFilteringStages.java:97)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:147)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:259)
at org.glassfish.jersey.client.JerseyInvocation.lambda$invoke$1(JerseyInvocation.java:743)
at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
at org.glassfish.jersey.internal.Errors.process(Errors.java:205)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:390)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:741)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:432)
at org.glassfish.jersey.client.JerseyCompletionStageRxInvoker.lambda$method$1(JerseyCompletionStageRxInvoker.java:46)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
... 3 more
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type 'application/'
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:428)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:422)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:307)
... 18 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type 'application/'
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:69)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:37)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:196)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:426)
... 20 more
Caused by: java.text.ParseException: End of header.
at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.getNextCharacter(HttpHeaderReaderImpl.java:155)
at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.next(HttpHeaderReaderImpl.java:116)
at org.glassfish.jersey.message.internal.HttpHeaderReaderImpl.next(HttpHeaderReaderImpl.java:111)
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextToken(HttpHeaderReader.java:104)
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:90)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:67)
... 23 more
github-MediaTypeProvider
我无法控制此第 3 方服务器,我必须能够处理此请求。
反正有这个吗?
一些属性、设置、注册自定义媒体类型提供程序,什么?
附:
我已经成功地使用ByteBuddy 在运行时重新定义了这个方法,并用一些额外的特殊调味料来处理错误,但这是一个重大的黑客攻击......如果它存在,我希望有更好的选择。
客户端配置
final Client client = ClientBuilder.newBuilder()
.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.CHUNKED)
.property(ClientProperties.FOLLOW_REDIRECTS, false)
.sslContext(tls)
.hostnameVerifier(new NoOpHostnameVerifier())
.register(new CookiePersistFilter(NARRATIVE)) // @Priority(HEADER_DECORATOR)
.register(new LoggingFilter(NARRATIVE)) // @Priority(USER)
.register(MyFilter.class) // @Priority(50000)
.register(JsonReader.class)
.register(JsonWriter.class)
.register(HTMLReader.class)
.register(MultiPartFeature.class)
.build();
过滤器按以下顺序执行:
- 我的过滤器
- 日志过滤器
- CookiePersistFilter
【问题讨论】:
-
由于在调用
readEntity()之前不会出现此错误,我认为您可以在调用readEntity()之前手动设置响应标头。喜欢response.getHeaders().putSingle("Content-Type", "application/json") -
嗨@PaulSamsotha,谢谢你的想法。我已经更新了在过滤器中显示这种情况的堆栈跟踪。因此,我认为我需要在读取实体之前处理此问题,否则它会通过任何其他过滤器以确保安全。我可以使用响应过滤器吗?如果是这样,我如何优先考虑它?我尝试使用 @Rank(1) 进行注释,但它似乎对排序没有任何影响(它首先调用我的另一个过滤器,排名 Priorities.USER 爆炸了)。
-
使用优先级的正确方法是使用
@Priority或者当您调用register()-- 使用让您指定数字优先级的重载。 -
我的错@PaulSamsotha,我混淆了排名和优先级。所以我尝试了优先级,它奏效了。但是,订购不是我所期望的。对于我的球衣客户,当优先级文档说明相反时,它似乎按降序排序(最高数字,最高优先级)。这是预期的吗?
-
为了以防万一,我在客户端配置中添加了过滤器排序。
标签: java jax-rs jersey-2.0 jersey-client