Closed jluehe closed 4 months ago
I believe this is one of the tasks that should have been solvable by HeaderDelegate
and associated HeaderDelegateProvider
SPI, so that each customer can specify whatever he desires. The SPI has been a bit overlooked in the past, but that's the idea.
Would it help in your case?
Thank you, @jansupol! That sounds like an interesting idea! Let me play with it and see if I can get it to work!
@jansupol, I was able to pinpoint where the whitespace gets stripped in Jersey 2:
package com.sun.jersey.core.impl.provider.header;
public class MediaTypeProvider implements HeaderDelegateProvider<MediaType> {
@Override
public String toString(MediaType header) {
StringBuilder b = new StringBuilder();
b.append(header.getType()).append('/').append(header.getSubtype());
for (Map.Entry<String, String> e : header.getParameters().entrySet()) {
b.append("; ").append(e.getKey()).append('='); <<<<== whitespace added after semicolon
WriterUtil.appendQuotedIfNonToken(b, e.getValue());
}
return b.toString();
}
...
}
package org.glassfish.jersey.message.internal;
public class MediaTypeProvider implements HeaderDelegateProvider<MediaType> {
@Override
public String toString(MediaType header) {
throwIllegalArgumentExceptionIfNull(header, MEDIA_TYPE_IS_NULL);
StringBuilder b = new StringBuilder();
b.append(header.getType()).append('/').append(header.getSubtype());
for (Map.Entry<String, String> e : header.getParameters().entrySet()) {
b.append(";").append(e.getKey()).append('='); <<<<== no more whitespace added after semicolon
StringBuilderUtils.appendQuotedIfNonToken(b, e.getValue());
}
return b.toString();
}
...
}
@jansupol, can you tell me how I can replace/override Jersey's MediaTypeProvider with my own?
I see Jersey's RuntimeDelegateImpl
getting initialized as follows:
package org.glassfish.jersey.server.internal;
public RuntimeDelegateImpl() {
super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
}
where the MessagingBinders.HeaderDelegateProviders
constructor uses Jersey's built-in HeaderDelegateProviders:
public HeaderDelegateProviders() {
Set<HeaderDelegateProvider> providers = new HashSet<>();
providers.add(new CacheControlProvider());
providers.add(new CookieProvider());
providers.add(new DateProvider());
providers.add(new EntityTagProvider());
providers.add(new LinkProvider());
providers.add(new LocaleProvider());
providers.add(new MediaTypeProvider());
providers.add(new NewCookieProvider());
providers.add(new StringHeaderProvider());
providers.add(new UriProvider());
this.providers = providers;
}
I had hoped it would also consider any custom HeaderDelegateProviders declared in META-INF/services
as described here: https://eclipse-ee4j.github.io/jersey.github.io/apidocs/2.34/jersey/org/glassfish/jersey/spi/HeaderDelegateProvider.html
Do you have any recommendation for how to make this work? I noticed the same question was asked here: https://stackoverflow.com/questions/62297701/how-to-inject-custom-implementation-of-org-glassfish-jersey-spi-headerdelegatepr, but it was never answered.
Thank you!
@jansupol, what I ended up doing is extend org.glassfish.jersey.server.internal.RuntimeDelegateImpl
and have my subclass (declared in META-INF/services/javax.ws.rs.ext.RuntimeDelegate
) override createHeaderDelegate
...
Has there been any consideration given to restore/preserve the whitespace character separating the
charset=
from the semicolon (trailing the MIME type) in theContent-Type
header? Or could this be made configurable at a minimum?See https://download.oracle.com/javaee-archive/jersey.java.net/users/2013/04/17157.html where this was brought up originally.
Apologies if this was already discussed.
Thank you!