Jersey 客户端错误 - 无法解析无效的 Content-Type 标头(需要解决方法)
Posted
技术标签:
【中文标题】Jersey 客户端错误 - 无法解析无效的 Content-Type 标头(需要解决方法)【英文标题】:Jersey Client Error - Unable to Parse Invalid Content-Type Header (need workaround) 【发布时间】: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,我混淆了排名和优先级。所以我尝试了优先级,它奏效了。但是,订购不是我所期望的。对于我的球衣客户,当优先级文档说明相反时,它似乎按降序排序(最高数字,最高优先级)。这是预期的吗?
为了以防万一,我在客户端配置中添加了过滤器排序。
【参考方案1】:
正如Paul Samsotha 指出的那样,我可以使用ClientResponseFilter 使用高优先级来解决此问题。这是一种可以做到的方法。
import javax.annotation.Priority;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import com.selinc.winchester.common.narrative.INarrative;
import com.selinc.winchester.sentinel.Sentinel;
import com.selinc.winchester.wrestler.ResponsePriorities;
@Provider
@Priority(25000) // Note the priority ordering is reverse of ClientRequestFilter
public final class ResponseHeaderWorkaroundFilter implements ClientResponseFilter
@Override
public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext)
try
// Attempt to read the Content-Type header.
responseContext.getMediaType();
catch (Throwable error)
// On error, set the Content-Type header to some default value.
responseContext.getHeaders()
.putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
【讨论】:
以上是关于Jersey 客户端错误 - 无法解析无效的 Content-Type 标头(需要解决方法)的主要内容,如果未能解决你的问题,请参考以下文章
MAVEN BUILD FAILURE - 无法解析项目 XYZ 的依赖关系