Skip to content
Permalink
Browse files
8265123: Add static factory methods to com.sun.net.httpserver.Filter
Co-authored-by: Michael McMahon <michaelm@openjdk.org>
Reviewed-by: chegar, michaelm, dfuchs
  • Loading branch information
FrauBoes and Michael-Mc-Mahon committed Apr 29, 2021
1 parent 39abac9 commit 115a413ee45b08d25fc827b2f465fbb4ef4157ad
Show file tree
Hide file tree
Showing 3 changed files with 409 additions and 3 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,8 @@
import java.io.OutputStream;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.function.Consumer;

/**
* A filter used to pre- and post-process incoming requests. Pre-processing occurs
@@ -140,4 +142,111 @@ public abstract void doFilter (HttpExchange exchange, Chain chain)
*/
public abstract String description ();

/**
* Returns a pre-processing {@code Filter} with the given description and
* operation.
*
* <p>The {@link 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 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 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) {
Objects.requireNonNull(description);
Objects.requireNonNull(operation);
return new Filter() {
@Override
public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
operation.accept(exchange);
chain.doFilter(exchange);
}
@Override
public String description() {
return description;
}
};
}

/**
* Returns a post-processing {@code Filter} with the given description and
* operation.
*
* <p>The {@link 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 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 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) {
Objects.requireNonNull(description);
Objects.requireNonNull(operation);
return new Filter() {
@Override
public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
chain.doFilter(exchange);
operation.accept(exchange);
}
@Override
public String description() {
return description;
}
};
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -659,7 +659,9 @@ public void close() throws IOException {
r = wrapper.wrapAndSend (buf);
stat = r.result.getHandshakeStatus();
}
assert r.result.getStatus() == Status.CLOSED;
assert r.result.getStatus() == Status.CLOSED
: "status is: " + r.result.getStatus()
+ ", handshakeStatus is: " + stat;
}
}
}

1 comment on commit 115a413

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 115a413 Apr 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.