Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8266213

Add static factory methods to com.sun.net.httpserver.Filter

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 17
    • core-libs
    • None
    • source
    • minimal
    • Java API
    • JDK

      Summary

      This CSR proposes to add two new static factory methods to com.sun.net.httpserver.Filter to facilitate the creation of pre- and post-processing filters, Filter beforeHandler(String description, Consumer<HttpExchange> operation) and Filter afterHandler(String description, Consumer<HttpExchange> operation). Filters are used to process an exchange before and/or after it is handled. While the notion of pre- and post-processing filters already exists, these new methods provide a convenient means for creating such filters.

      Problem

      Currently, there is no convenient way to create pre- or post-processing filters. Instead, the abstract Filter class has to be extended by a subclass that implements the filter logic. An instance of the subclass is then added to an HttpContext. Multiple filters can be added to a context and a filter typically applies a small set of operations to an exchange. As such, filters lend themselves to factory methods, which can provide a more compact way of filter creation.

      Solution

      The two factory methods avoid the overhead of subclassing the Filter class. A pre- or post-processing filter can easily be created by passing the description and the operation of the filter to the static methods.

      Specification

      src/jdk.httpserver/share/classes/com/sun/net/httpserver/Filter.java

      +    /**
      +     * Returns a pre-processing {@code Filter} with the given description and
      +     * operation.
      +     *
      +     * <p>The {@link java.util.function.Consumer operation} is the effective implementation of the
      +     * filter. It is executed for each {@code HttpExchange} before invoking
      +     * either the next filter in the chain or the exchange handler (if this is
      +     * the final filter in the chain).
      +     *
      +     * @apiNote
      +     * A beforeHandler filter is typically used to examine or modify the
      +     * exchange state before it is handled. The filter {@code operation} is
      +     * executed before {@link com.sun.net.httpserver.Filter.Chain#doFilter(HttpExchange)} is invoked,
      +     * so before any subsequent filters in the chain and the exchange handler
      +     * are executed. The filter {@code operation} is not expected to handle the
      +     * request or {@linkplain com.sun.net.httpserver.HttpExchange#sendResponseHeaders(int, long) send response headers},
      +     * since this is commonly done by the exchange handler.
      +     *
      +     * <p> Example of adding the {@code "Foo"} response header to all responses:
      +     * <pre>{@code
      +     *     var filter = Filter.beforeHandler("Add response header Foo",
      +     *                 e -> e.getResponseHeaders().set("Foo", "Bar"));
      +     *     httpContext.getFilters().add(filter);
      +     * }</pre>
      +     *
      +     * @param description the string to be returned from {@link #description()}
      +     * @param operation the operation of the returned filter
      +     * @return a filter whose operation is invoked before the exchange is handled
      +     * @throws NullPointerException if any argument is null
      +     * @since 17
      +     */
      +    public static Filter beforeHandler(String description, Consumer<HttpExchange> operation) { }
      
      
      +    /**
      +     * Returns a post-processing {@code Filter} with the given description and
      +     * operation.
      +     *
      +     * <p>The {@link java.util.function.Consumer operation} is the effective implementation of the
      +     * filter. It is executed for each {@code HttpExchange} after invoking
      +     * either the next filter in the chain or the exchange handler (if this
      +     * filter is the final filter in the chain).
      +     *
      +     * @apiNote
      +     * An afterHandler filter is typically used to examine the exchange state
      +     * rather than modifying it. The filter {@code operation} is executed after
      +     * {@link com.sun.net.httpserver.Filter.Chain#doFilter(HttpExchange)} is invoked, this means any
      +     * subsequent filters in the chain and the exchange handler have been
      +     * executed. The filter {@code operation} is not expected to handle the
      +     * exchange or {@linkplain com.sun.net.httpserver.HttpExchange#sendResponseHeaders(int, long) send the response headers}.
      +     * Doing so is likely to fail, since the exchange has commonly been handled
      +     * before the operation is invoked.
      +     *
      +     * <p> Example of adding a filter that logs the response code of all exchanges:
      +     * <pre>{@code
      +     *     var filter = Filter.afterHandler("Log response code", e -> log(e.getResponseCode());
      +     *     httpContext.getFilters().add(filter);
      +     * }</pre>
      +     *
      +     * <p> Example of adding a sequence of afterHandler filters to a context:<br>
      +     * The order in which the filter operations are invoked is reverse to the
      +     * order in which the filters are added to the context's filter-list.
      +     *
      +     * <pre>{@code
      +     *     var a1Set = Filter.afterHandler("Set a1", e -> e.setAttribute("a1", "some value"));
      +     *     var a1Get = Filter.afterHandler("Get a1", e -> doSomething(e.getAttribute("a1")));
      +     *     httpContext.getFilters().addAll(List.of(a1Get, a1Set));
      +     * }</pre>
      +     * <p>The operation of {@code a1Get} will be invoked after the operation of
      +     * {@code a1Set} because {@code a1Get} was added before {@code a1Set}.
      +     *
      +     * @param description the string to be returned from {@link #description()}
      +     * @param operation the operation of the returned filter
      +     * @return a filter whose operation is invoked after the exchange is handled
      +     * @throws NullPointerException if any argument is null
      +     * @since 17
      +     */
      +    public static Filter afterHandler(String description, Consumer<HttpExchange> operation) { }

            jboes Julia Boes (Inactive)
            jboes Julia Boes (Inactive)
            Chris Hegarty, Daniel Fuchs, Michael McMahon
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: