Skip to content

Commit

Permalink
Add an API for removing a route
Browse files Browse the repository at this point in the history
Related to #1669 

Co-authored-by: Violeta Georgieva <milesg78@gmail.com>
  • Loading branch information
ctlove0523 and violetagg committed Aug 16, 2021
1 parent 7608571 commit fab25e1
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
Expand Up @@ -29,6 +29,7 @@
import java.util.function.Function;
import java.util.function.Predicate;

import io.netty.handler.codec.http.HttpMethod;
import org.reactivestreams.Publisher;
import reactor.core.Exceptions;
import reactor.core.publisher.Mono;
Expand Down Expand Up @@ -74,23 +75,32 @@ public HttpServerRoutes directory(String uri, Path directory,
});
}

@Override
public HttpServerRoutes removeIf(Predicate<? super HttpRouteHandlerMetadata> condition) {
Objects.requireNonNull(condition, "condition");

handlers.removeIf(condition);

return this;
}

@Override
public HttpServerRoutes route(Predicate<? super HttpServerRequest> condition,
BiFunction<? super HttpServerRequest, ? super HttpServerResponse, ? extends Publisher<Void>> handler) {
Objects.requireNonNull(condition, "condition");
Objects.requireNonNull(handler, "handler");

if (condition instanceof HttpPredicate) {
HttpPredicate predicate = (HttpPredicate) condition;
HttpRouteHandler httpRouteHandler = new HttpRouteHandler(condition,
handler,
(HttpPredicate) condition, ((HttpPredicate) condition).uri);
handler, predicate, predicate.uri, predicate.method);

handlers.add(httpRouteHandler);
initialOrderHandlers.add(httpRouteHandler);

}
else {
HttpRouteHandler httpRouteHandler = new HttpRouteHandler(condition, handler, null, null);
HttpRouteHandler httpRouteHandler = new HttpRouteHandler(condition, handler, null, null, null);
handlers.add(httpRouteHandler);
initialOrderHandlers.add(httpRouteHandler);
}
Expand Down Expand Up @@ -119,6 +129,7 @@ public HttpServerRoutes noComparator() {

@Override
public Publisher<Void> apply(HttpServerRequest request, HttpServerResponse response) {
// find I/0 handler to process this request
final Iterator<HttpRouteHandler> iterator = handlers.iterator();
HttpRouteHandler cursor;

Expand Down Expand Up @@ -149,14 +160,18 @@ static final class HttpRouteHandler

final String path;

final HttpMethod method;

HttpRouteHandler(Predicate<? super HttpServerRequest> condition,
BiFunction<? super HttpServerRequest, ? super HttpServerResponse, ? extends Publisher<Void>> handler,
@Nullable Function<? super String, Map<String, String>> resolver,
@Nullable String path) {
@Nullable String path,
@Nullable HttpMethod method) {
this.condition = Objects.requireNonNull(condition, "condition");
this.handler = Objects.requireNonNull(handler, "handler");
this.resolver = resolver;
this.path = path;
this.method = method;
}

@Override
Expand All @@ -174,5 +189,10 @@ public boolean test(HttpServerRequest o) {
public String getPath() {
return path;
}

@Override
public HttpMethod getMethod() {
return method;
}
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package reactor.netty.http.server;

import io.netty.handler.codec.http.HttpMethod;
import reactor.util.annotation.Nullable;

import java.util.Comparator;
Expand All @@ -35,4 +36,13 @@ public interface HttpRouteHandlerMetadata {
*/
@Nullable
String getPath();

/**
* Get the http method this handler can handle
*
* @return the http method {@link HttpMethod}
* @since 1.0.11
*/
@Nullable
HttpMethod getMethod();
}
Expand Up @@ -251,6 +251,16 @@ default HttpServerRoutes put(String path,
return route(HttpPredicate.put(path), handler);
}

/**
* A generic route predicate that if matched already register I/O handler use
* {@link HttpServerRoutes#route(Predicate, BiFunction)} will be removed.
*
* @param condition a predicate given each http route handler {@link HttpRouteHandlerMetadata}
* @return this {@link HttpServerRoutes}
* @since 1.0.11
*/
HttpServerRoutes removeIf(Predicate<? super HttpRouteHandlerMetadata> condition);

/**
* A generic route predicate that if matched invoke the passed I/O handler.
*
Expand Down
Expand Up @@ -29,6 +29,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -2612,4 +2613,46 @@ private void doTestConnectionClosePropagatedAsError(String request) throws Excep
.isInstanceOf(AbortedException.class)
.hasMessage("Connection has been closed");
}

@Test
void testRemoveRoutes() {
HttpServerRoutes serverRoutes = HttpServerRoutes.newRoutes()
.get("/route1", (request, response) -> response.sendString(Mono.just("/route1")))
.get("/route2", (request, response) -> response.sendString(Mono.just("/route2")));

try {
disposableServer = HttpServer.create().handle(serverRoutes).bindNow();

StepVerifier.create(createClient(disposableServer.port()).get().uri("/route1")
.responseSingle((response, byteBufMono) -> byteBufMono.asString()))
.expectNext("/route1")
.verifyComplete();

StepVerifier.create(createClient(disposableServer.port()).get().uri("/route2")
.responseSingle((response, byteBufMono) -> byteBufMono.asString()))
.expectNext("/route2")
.verifyComplete();
}
finally {
if (disposableServer != null) {
disposableServer.disposeNow();
}
}

HttpServerRoutes serverRoutes1 = serverRoutes.removeIf(metadata -> Objects.equals(metadata.getPath(), "/route1")
&& metadata.getMethod().equals(HttpMethod.GET));

disposableServer = HttpServer.create().handle(serverRoutes1)
.bindNow();

StepVerifier.create(createClient(disposableServer.port()).get().uri("/route1")
.response())
.expectNextMatches(response -> response.status().equals(HttpResponseStatus.NOT_FOUND))
.verifyComplete();

StepVerifier.create(createClient(disposableServer.port()).get().uri("/route2")
.responseSingle((response, byteBufMono) -> byteBufMono.asString()))
.expectNext("/route2")
.verifyComplete();
}
}

0 comments on commit fab25e1

Please sign in to comment.