Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-2354

Custimize httpHeaders using ProxyConfig

    XMLWordPrintable

Details

    • Patch
    • Resolution: Unresolved
    • Major
    • None
    • 3.6.2.Final
    • jaxrs
    • None

    Description

      I came across a need to override @Consumes annotation and though that custom httpHeaders would do the trick.

      One cannot add these currently, but I had added earlier such feature to ClientInvoker and ProxyBuilder via ProxyConfig as shown below.

      org/jboss/resteasy/client/jaxrs/ProxyConfig.java
      package org.jboss.resteasy.client.jaxrs;
      
      import java.util.Map;
      
      import javax.ws.rs.core.MediaType;
      import javax.ws.rs.core.MultivaluedMap;
      
      public class ProxyConfig
      {
          private final ClassLoader loader;
          private Map<String, Object> properties;
          private MultivaluedMap<String, Object> httpHeaders;
          private MediaType defaultConsumes;
          private MediaType[] defaultProduces;
      
          @Deprecated
          public ProxyConfig(ClassLoader loader, MediaType defaultConsumes, MediaType... defaultProduces)
          {
              this(loader, null, null, defaultConsumes, defaultProduces);
          }
      
          public ProxyConfig(ClassLoader loader, Map<String, Object> properties, MultivaluedMap<String, Object> httpHeaders, MediaType defaultConsumes, MediaType... defaultProduces)
          {
              this.loader = loader;
              this.httpHeaders = httpHeaders;
              this.properties = properties;
              this.defaultConsumes = defaultConsumes;
              this.defaultProduces = defaultProduces;
          }
      
          public ClassLoader getLoader()
          {
              return loader;
          }
      
          public Map<String, Object> getProperties()
          {
              return this.properties;
          }
      
          public MediaType getDefaultConsumes()
          {
              return defaultConsumes;
          }
      
          public MediaType[] getDefaultProduces()
          {
              return defaultProduces;
          }
      
          public MultivaluedMap<String, Object> getHttpHeaders()
          {
              return this.httpHeaders;
          }
      
      }
      

      Then I noticed that for some reason the MediaType is resolved to either defaultConsumes or to the @Consumes annotation (doesn't work without either of them currently) and the one I gave as HttpHeaders.CONTENT_TYPE is neglected.
      The magic happened inside ProcessorFactory where the of was course no reference to HttpHeaders that I'd just patched in.

      if (this.httpHeaders != null)
                  {
                      clientInvocationBuilder.getHeaders().getHeaders().putAll(
                          this.httpHeaders);
                  }
      

      By adding the following method I managed to change the preference so that the is a case specific MediaType declared (multipart/mixed with a custom boundary for instance) is preferred over the annotations+fallback mediatype.

      org/jboss/resteasy/client/jaxrs/internal/proxy/processors/ProcessorFactory.java
      @@ -7,6 +7,7 @@
       import java.lang.reflect.Type;
       import java.lang.reflect.TypeVariable;
       import java.util.Arrays;
      +import java.util.Optional;
       import java.util.Stack;
       
       import javax.ws.rs.BeanParam;
      @@ -19,7 +20,9 @@
       import javax.ws.rs.QueryParam;
       import javax.ws.rs.core.Context;
       import javax.ws.rs.core.Cookie;
      +import javax.ws.rs.core.HttpHeaders;
       import javax.ws.rs.core.MediaType;
      +import javax.ws.rs.core.MultivaluedMap;
       
       import org.jboss.resteasy.annotations.Form;
       import org.jboss.resteasy.client.ClientURI;
      @@ -33,6 +36,7 @@
       import org.jboss.resteasy.client.jaxrs.internal.proxy.processors.webtarget.MatrixParamProcessor;
       import org.jboss.resteasy.client.jaxrs.internal.proxy.processors.webtarget.PathParamProcessor;
       import org.jboss.resteasy.client.jaxrs.internal.proxy.processors.webtarget.QueryParamProcessor;
      +import org.jboss.resteasy.core.Headers;
       import org.jboss.resteasy.util.FindAnnotation;
       import org.jboss.resteasy.util.MediaTypeHelper;
       
      @@ -46,6 +50,11 @@
       
          public static Object[] createProcessors(Class declaringClass, Method method, ClientConfiguration configuration, MediaType defaultConsumes)
          {
      +       return createProcessors(declaringClass, method, configuration, defaultConsumes, new Headers<>()); 
      +   }
      +
      +   public static Object[] createProcessors(Class declaringClass, Method method, ClientConfiguration configuration, MediaType defaultConsumes, MultivaluedMap<String, Object> httpHeaders)
      +   {       
             Object[] params = new Object[method.getParameterTypes().length];
             for (int i = 0; i < method.getParameterTypes().length; i++)
             {
      @@ -56,7 +65,7 @@
                   genericType = getTypeArgument((TypeVariable)genericType, declaringClass, method.getDeclaringClass());
                }
                AccessibleObject target = method;
      -         params[i] = ProcessorFactory.createProcessor(declaringClass, configuration, type, annotations, genericType, target, defaultConsumes, false);
      +         params[i] = ProcessorFactory.createProcessor(declaringClass, configuration, type, annotations, genericType, target, defaultConsumes, httpHeaders, false);
             }
             return params;
          }
      @@ -70,9 +79,17 @@
          }
       
          public static Object createProcessor(Class<?> declaring,
      +       ClientConfiguration configuration, Class<?> type,
      +       Annotation[] annotations, Type genericType, AccessibleObject target, MediaType defaultConsumes,
      +       boolean ignoreBody)
      +   {
      +       return createProcessor(declaring, configuration, type, annotations, genericType, target, defaultConsumes, null, ignoreBody);
      +   }
      +
      +   public static Object createProcessor(Class<?> declaring,
                                                   ClientConfiguration configuration, Class<?> type,
                                                   Annotation[] annotations, Type genericType, AccessibleObject target, MediaType defaultConsumes,
      -                                            boolean ignoreBody)
      +                                            MultivaluedMap<String, Object> httpHeaders, boolean ignoreBody)
          {
             Object processor = null;
       
      @@ -142,7 +159,9 @@
             }
             else if (!ignoreBody)
             {
      -         MediaType mediaType = MediaTypeHelper.getConsumes(declaring, target);
      +         MediaType mediaType = Optional.ofNullable(httpHeaders).map(headers -> headers.getFirst(HttpHeaders.CONTENT_TYPE)).map(contentType -> 
      +           contentType instanceof String ? MediaType.valueOf((String) contentType) : (MediaType) contentType
      +         ).orElseGet(() -> MediaTypeHelper.getConsumes(declaring, target));
                if(mediaType == null)
                   mediaType = defaultConsumes;
                if (mediaType == null)
      

      Attachments

        Activity

          People

            Unassigned Unassigned
            tuomas_kiviaho Tuomas Kiviaho (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: