Talk about feign’s RequestInterceptor

  feign

Order

This article mainly studies feign’s RequestInterceptor

RequestInterceptor

feign-core-10.2.3-sources.jar! /feign/RequestInterceptor.java

public interface RequestInterceptor {

  /**
   * Called for every request. Add data using methods on the supplied {@link RequestTemplate}.
   */
  void apply(RequestTemplate template);
}
  • The RequestInterceptor interface defines the apply method, and its parameter is RequestTemplate; ; It has an abstract class called BaseRequestInterceptor, and several implementation classes are respectively BasicAuthRequestInterceptor, Feign AcceptGzIPenCodeInterceptor, Feign ContentGzIPenCodeInterceptor

BasicAuthRequestInterceptor

feign-core-10.2.3-sources.jar! /feign/auth/BasicAuthRequestInterceptor.java

public class BasicAuthRequestInterceptor implements RequestInterceptor {

  private final String headerValue;

  /**
   * Creates an interceptor that authenticates all requests with the specified username and password
   * encoded using ISO-8859-1.
   *
   * @param username the username to use for authentication
   * @param password the password to use for authentication
   */
  public BasicAuthRequestInterceptor(String username, String password) {
    this(username, password, ISO_8859_1);
  }

  /**
   * Creates an interceptor that authenticates all requests with the specified username and password
   * encoded using the specified charset.
   *
   * @param username the username to use for authentication
   * @param password the password to use for authentication
   * @param charset the charset to use when encoding the credentials
   */
  public BasicAuthRequestInterceptor(String username, String password, Charset charset) {
    checkNotNull(username, "username");
    checkNotNull(password, "password");
    this.headerValue = "Basic " + base64Encode((username + ":" + password).getBytes(charset));
  }

  /*
   * This uses a Sun internal method; if we ever encounter a case where this method is not
   * available, the appropriate response would be to pull the necessary portions of Guava's
   * BaseEncoding class into Util.
   */
  private static String base64Encode(byte[] bytes) {
    return Base64.encode(bytes);
  }

  @Override
  public void apply(RequestTemplate template) {
    template.header("Authorization", headerValue);
  }
}
  • BasicAuthRequestInterceptor implements the RequestInterceptor interface, and its apply method adds a header named Authorization to the RequestTemplate

BaseRequestInterceptor

spring-cloud-openfeign-core-2.2.0.M1-sources.jar! /org/springframework/cloud/openfeign/encoding/BaseRequestInterceptor.java

public abstract class BaseRequestInterceptor implements RequestInterceptor {

    /**
     * The encoding properties.
     */
    private final FeignClientEncodingProperties properties;

    /**
     * Creates new instance of {@link BaseRequestInterceptor}.
     * @param properties the encoding properties
     */
    protected BaseRequestInterceptor(FeignClientEncodingProperties properties) {
        Assert.notNull(properties, "Properties can not be null");
        this.properties = properties;
    }

    /**
     * Adds the header if it wasn't yet specified.
     * @param requestTemplate the request
     * @param name the header name
     * @param values the header values
     */
    protected void addHeader(RequestTemplate requestTemplate, String name,
            String... values) {

        if (!requestTemplate.headers().containsKey(name)) {
            requestTemplate.header(name, values);
        }
    }

    protected FeignClientEncodingProperties getProperties() {
        return this.properties;
    }

}
  • BaseRequestInterceptor defines the addHeader method, adding a header with a non-duplicate name to requestTemplate

FeignAcceptGzipEncodingInterceptor

spring-cloud-openfeign-core-2.2.0.M1-sources.jar! /org/springframework/cloud/openfeign/encoding/FeignAcceptGzipEncodingInterceptor.java

public class FeignAcceptGzipEncodingInterceptor extends BaseRequestInterceptor {

    /**
     * Creates new instance of {@link FeignAcceptGzipEncodingInterceptor}.
     * @param properties the encoding properties
     */
    protected FeignAcceptGzipEncodingInterceptor(
            FeignClientEncodingProperties properties) {
        super(properties);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void apply(RequestTemplate template) {

        addHeader(template, HttpEncoding.ACCEPT_ENCODING_HEADER,
                HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING);
    }

}
  • Feigningacceptgzipendinginterceptor inherits BaseRequestInterceptor, and its apply method adds a header named Accept-Encoding with values gzip and deflate to RequestTemplate.

FeignContentGzipEncodingInterceptor

spring-cloud-openfeign-core-2.2.0.M1-sources.jar! /org/springframework/cloud/openfeign/encoding/FeignContentGzipEncodingInterceptor.java

public class FeignContentGzipEncodingInterceptor extends BaseRequestInterceptor {

    /**
     * Creates new instance of {@link FeignContentGzipEncodingInterceptor}.
     * @param properties the encoding properties
     */
    protected FeignContentGzipEncodingInterceptor(
            FeignClientEncodingProperties properties) {
        super(properties);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void apply(RequestTemplate template) {

        if (requiresCompression(template)) {
            addHeader(template, HttpEncoding.CONTENT_ENCODING_HEADER,
                    HttpEncoding.GZIP_ENCODING, HttpEncoding.DEFLATE_ENCODING);
        }
    }

    /**
     * Returns whether the request requires GZIP compression.
     * @param template the request template
     * @return true if request requires compression, false otherwise
     */
    private boolean requiresCompression(RequestTemplate template) {

        final Map<String, Collection<String>> headers = template.headers();
        return matchesMimeType(headers.get(HttpEncoding.CONTENT_TYPE))
                && contentLengthExceedThreshold(headers.get(HttpEncoding.CONTENT_LENGTH));
    }

    /**
     * Returns whether the request content length exceed configured minimum size.
     * @param contentLength the content length header value
     * @return true if length is grater than minimum size, false otherwise
     */
    private boolean contentLengthExceedThreshold(Collection<String> contentLength) {

        try {
            if (contentLength == null || contentLength.size() != 1) {
                return false;
            }

            final String strLen = contentLength.iterator().next();
            final long length = Long.parseLong(strLen);
            return length > getProperties().getMinRequestSize();
        }
        catch (NumberFormatException ex) {
            return false;
        }
    }

    /**
     * Returns whether the content mime types matches the configures mime types.
     * @param contentTypes the content types
     * @return true if any specified content type matches the request content types
     */
    private boolean matchesMimeType(Collection<String> contentTypes) {
        if (contentTypes == null || contentTypes.size() == 0) {
            return false;
        }

        if (getProperties().getMimeTypes() == null
                || getProperties().getMimeTypes().length == 0) {
            // no specific mime types has been set - matching everything
            return true;
        }

        for (String mimeType : getProperties().getMimeTypes()) {
            if (contentTypes.contains(mimeType)) {
                return true;
            }
        }

        return false;
    }

}
  • Feiigncontentgzipencodinginterceptor inherits BaseRequestInterceptor. its application method first determines whether compression is required, that is, whether mimeType meets the requirements and whether the content size exceeds the threshold. if compression is required, a header named Content-Encoding with gzip and deflate is added.

Summary

  • The RequestInterceptor interface defines the apply method, and its parameter is RequestTemplate; ; It has an abstract class called BaseRequestInterceptor, and several implementation classes are respectively BasicAuthRequestInterceptor, Feign AcceptGzIPenCodeInterceptor, Feign ContentGzIPenCodeInterceptor
  • BasicAuthRequestInterceptor implements the RequestInterceptor interface, and its apply method adds a header named Authorization to the RequestTemplate
  • BaseRequestInterceptor defines the addHeader method, adding a header; with a non-duplicate name to requestTemplate; FeigningacceptgzipencordingInterceptor inherits BaseRequestInterceptor. Its apply method adds a header; named Accept-Encoding with GZIP and Defeat to RequestTemplate. Feiigncontentgzipencodinginterceptor inherits BaseRequestInterceptor. its application m ethod first determines whether compression is required, that is, whether mimeType meets the requirements and whether the content size exceeds the threshold. if compression is required, a header named Content-Encoding with gzip and deflate is added.

doc