mirror of
https://github.com/google/nomulus
synced 2026-01-03 11:45:39 +00:00
Remove WHOIS classes and configuration (#2859)
This is steps one and two of b/454947209 We already haven't been serving WHOIS for a while, so there's no point in keeping the old code around. This can simplify some code paths in the future (like, certain foreign-key-loads that are only used in WHOIS queries).
This commit is contained in:
@@ -29,7 +29,6 @@ public class Prober {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// Obtains WebWhois Sequence provided by proberComponent
|
||||
ImmutableSet<ProbingSequence> sequences = ImmutableSet.copyOf(proberComponent.sequences());
|
||||
|
||||
// Tells Sequences to start running
|
||||
|
||||
@@ -20,7 +20,6 @@ import dagger.Provides;
|
||||
import google.registry.monitoring.blackbox.connection.ProbingAction;
|
||||
import google.registry.monitoring.blackbox.module.CertificateModule;
|
||||
import google.registry.monitoring.blackbox.module.EppModule;
|
||||
import google.registry.monitoring.blackbox.module.WebWhoisModule;
|
||||
import google.registry.networking.handler.SslClientInitializer;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.SystemClock;
|
||||
@@ -102,13 +101,10 @@ public class ProberModule {
|
||||
@Component(
|
||||
modules = {
|
||||
ProberModule.class,
|
||||
WebWhoisModule.class,
|
||||
EppModule.class,
|
||||
CertificateModule.class
|
||||
})
|
||||
public interface ProberComponent {
|
||||
|
||||
// Standard WebWhois sequence
|
||||
Set<ProbingSequence> sequences();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.handler;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import google.registry.monitoring.blackbox.connection.ProbingAction;
|
||||
import google.registry.monitoring.blackbox.connection.Protocol;
|
||||
import google.registry.monitoring.blackbox.exception.ConnectionException;
|
||||
import google.registry.monitoring.blackbox.exception.FailureException;
|
||||
import google.registry.monitoring.blackbox.exception.UndeterminedStateException;
|
||||
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
|
||||
import google.registry.monitoring.blackbox.message.HttpResponseMessage;
|
||||
import google.registry.monitoring.blackbox.message.InboundMessageType;
|
||||
import google.registry.monitoring.blackbox.module.WebWhoisModule.HttpWhoisProtocol;
|
||||
import google.registry.monitoring.blackbox.module.WebWhoisModule.HttpsWhoisProtocol;
|
||||
import google.registry.monitoring.blackbox.module.WebWhoisModule.WebWhoisProtocol;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import jakarta.inject.Inject;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Subclass of {@link ActionHandler} that deals with the WebWhois Sequence
|
||||
*
|
||||
* <p>Main purpose is to verify {@link HttpResponseMessage} received is valid. If the response
|
||||
* implies a redirection it follows the redirection until either an Error Response is received, or
|
||||
* {@link HttpResponseStatus#OK} is received
|
||||
*/
|
||||
public class WebWhoisActionHandler extends ActionHandler {
|
||||
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
/* Dagger injected components necessary for redirect responses: */
|
||||
|
||||
/** {@link Bootstrap} necessary for remaking connection on redirect response. */
|
||||
private final Bootstrap bootstrap;
|
||||
|
||||
/** {@link Protocol} for when redirected to http endpoint. */
|
||||
private final Protocol httpWhoisProtocol;
|
||||
|
||||
/** {@link Protocol} for when redirected to https endpoint. */
|
||||
private final Protocol httpsWhoisProtocol;
|
||||
|
||||
/** {@link HttpRequestMessage} that represents default GET message to be sent on redirect. */
|
||||
private final HttpRequestMessage requestMessage;
|
||||
|
||||
@Inject
|
||||
public WebWhoisActionHandler(
|
||||
@WebWhoisProtocol Bootstrap bootstrap,
|
||||
@HttpWhoisProtocol Protocol httpWhoisProtocol,
|
||||
@HttpsWhoisProtocol Protocol httpsWhoisProtocol,
|
||||
HttpRequestMessage requestMessage) {
|
||||
|
||||
this.bootstrap = bootstrap;
|
||||
this.httpWhoisProtocol = httpWhoisProtocol;
|
||||
this.httpsWhoisProtocol = httpsWhoisProtocol;
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* After receiving {@link HttpResponseMessage}, either notes success and marks future as finished,
|
||||
* notes an error in the received {@link URL} and throws a {@link ConnectionException}, received a
|
||||
* response indicating a Failure, or receives a redirection response, where it follows the
|
||||
* redirects until receiving one of the previous three responses.
|
||||
*/
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, InboundMessageType msg)
|
||||
throws FailureException, UndeterminedStateException {
|
||||
|
||||
HttpResponseMessage response = (HttpResponseMessage) msg;
|
||||
|
||||
if (response.status().equals(HttpResponseStatus.OK)) {
|
||||
logger.atInfo().log("Received Successful HttpResponseStatus");
|
||||
logger.atInfo().log("Response Received: %s", response);
|
||||
|
||||
// On success, we always pass message to ActionHandler's channelRead0 method.
|
||||
super.channelRead0(ctx, msg);
|
||||
|
||||
} else if (response.status().equals(HttpResponseStatus.MOVED_PERMANENTLY)
|
||||
|| response.status().equals(HttpResponseStatus.FOUND)) {
|
||||
// TODO - Fix checker to better determine when we have encountered a redirection response.
|
||||
|
||||
// Obtain url to be redirected to
|
||||
URL url;
|
||||
try {
|
||||
url = new URI(response.headers().get("Location")).toURL();
|
||||
} catch (MalformedURLException | URISyntaxException | IllegalArgumentException e) {
|
||||
// in case of error, log it, and let ActionHandler's exceptionThrown method deal with it
|
||||
throw new FailureException(
|
||||
"Redirected Location was invalid. Given Location was: "
|
||||
+ response.headers().get("Location"));
|
||||
}
|
||||
// From url, extract new host, port, and path
|
||||
String newHost = url.getHost();
|
||||
String newPath = url.getPath();
|
||||
|
||||
logger.atInfo().log(
|
||||
String.format(
|
||||
"Redirected to %s with host: %s, port: %d, and path: %s",
|
||||
url, newHost, url.getDefaultPort(), newPath));
|
||||
|
||||
// Construct new Protocol to reflect redirected host, path, and port
|
||||
Protocol newProtocol;
|
||||
if (url.getProtocol().equals(httpWhoisProtocol.name())) {
|
||||
newProtocol = httpWhoisProtocol;
|
||||
} else if (url.getProtocol().equals(httpsWhoisProtocol.name())) {
|
||||
newProtocol = httpsWhoisProtocol;
|
||||
} else {
|
||||
throw new FailureException(
|
||||
"Redirection Location port was invalid. Given protocol name was: " + url.getProtocol());
|
||||
}
|
||||
|
||||
// Obtain HttpRequestMessage with modified headers to reflect new host and path.
|
||||
HttpRequestMessage httpRequest = requestMessage.modifyMessage(newHost, newPath);
|
||||
|
||||
// Create new probingAction that takes in the new Protocol and HttpRequestMessage with no
|
||||
// delay
|
||||
ProbingAction redirectedAction =
|
||||
ProbingAction.builder()
|
||||
.setBootstrap(bootstrap)
|
||||
.setProtocol(newProtocol)
|
||||
.setOutboundMessage(httpRequest)
|
||||
.setDelay(Duration.ZERO)
|
||||
.setHost(newHost)
|
||||
.build();
|
||||
|
||||
// close this channel as we no longer need it
|
||||
ChannelFuture future = ctx.close();
|
||||
future.addListener(
|
||||
f -> {
|
||||
if (f.isSuccess()) {
|
||||
logger.atInfo().log("Successfully closed connection.");
|
||||
} else {
|
||||
logger.atWarning().log("Channel was unsuccessfully closed.");
|
||||
}
|
||||
|
||||
// Once channel is closed, establish new connection to redirected host, and repeat
|
||||
// same actions
|
||||
ChannelFuture secondFuture = redirectedAction.call();
|
||||
|
||||
// Once we have a successful call, set original ChannelPromise as success to tell
|
||||
// ProbingStep we can move on
|
||||
secondFuture.addListener(
|
||||
f2 -> {
|
||||
if (f2.isSuccess()) {
|
||||
super.channelRead0(ctx, msg);
|
||||
} else {
|
||||
if (f2 instanceof FailureException) {
|
||||
throw new FailureException(f2.cause());
|
||||
} else {
|
||||
throw new UndeterminedStateException(f2.cause());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Add in metrics Handling that informs MetricsCollector the response was a FAILURE
|
||||
logger.atWarning().log(String.format("Received unexpected response: %s", response.status()));
|
||||
throw new FailureException("Response received from remote site was: " + response.status());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.handler;
|
||||
|
||||
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
|
||||
import google.registry.monitoring.blackbox.message.HttpResponseMessage;
|
||||
import google.registry.monitoring.blackbox.message.InboundMessageType;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* {@link io.netty.channel.ChannelHandler} that converts inbound {@link FullHttpResponse} to custom
|
||||
* type {@link HttpResponseMessage} and retains {@link HttpRequestMessage} in case of reuse for
|
||||
* redirection.
|
||||
*/
|
||||
public class WebWhoisMessageHandler extends ChannelDuplexHandler {
|
||||
|
||||
@Inject
|
||||
public WebWhoisMessageHandler() {}
|
||||
|
||||
/** Retains {@link HttpRequestMessage} and calls super write method. */
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
|
||||
throws Exception {
|
||||
HttpRequestMessage request = (HttpRequestMessage) msg;
|
||||
request.retain();
|
||||
super.write(ctx, request, promise);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts {@link FullHttpResponse} to {@link HttpResponseMessage}, so it is an {@link
|
||||
* InboundMessageType} instance.
|
||||
*/
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
FullHttpResponse originalResponse = (FullHttpResponse) msg;
|
||||
HttpResponseMessage response = new HttpResponseMessage(originalResponse);
|
||||
super.channelRead(ctx, response);
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.module;
|
||||
|
||||
import static google.registry.monitoring.blackbox.connection.ProbingAction.REMOTE_ADDRESS_KEY;
|
||||
import static google.registry.monitoring.blackbox.connection.Protocol.PROTOCOL_KEY;
|
||||
import static google.registry.networking.handler.SslClientInitializer.createSslClientInitializerWithSystemTrustStore;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoSet;
|
||||
import google.registry.monitoring.blackbox.ProbingSequence;
|
||||
import google.registry.monitoring.blackbox.ProbingStep;
|
||||
import google.registry.monitoring.blackbox.connection.Protocol;
|
||||
import google.registry.monitoring.blackbox.handler.WebWhoisActionHandler;
|
||||
import google.registry.monitoring.blackbox.handler.WebWhoisMessageHandler;
|
||||
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
|
||||
import google.registry.monitoring.blackbox.metric.MetricsCollector;
|
||||
import google.registry.monitoring.blackbox.token.WebWhoisToken;
|
||||
import google.registry.networking.handler.SslClientInitializer;
|
||||
import google.registry.util.Clock;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.inject.Qualifier;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* A module that provides the components necessary for and the overall {@link ProbingSequence} to
|
||||
* probe WebWHOIS.
|
||||
*/
|
||||
@Module
|
||||
public class WebWhoisModule {
|
||||
|
||||
private static final String HTTP_PROTOCOL_NAME = "http";
|
||||
private static final String HTTPS_PROTOCOL_NAME = "https";
|
||||
private static final int HTTP_WHOIS_PORT = 80;
|
||||
private static final int HTTPS_WHOIS_PORT = 443;
|
||||
|
||||
/** Standard length of messages used by Proxy. Equates to 0.5 MB. */
|
||||
private static final int maximumMessageLengthBytes = 512 * 1024;
|
||||
|
||||
/** {@link Provides} only step used in WebWhois sequence. */
|
||||
@Provides
|
||||
@WebWhoisProtocol
|
||||
static ProbingStep provideWebWhoisStep(
|
||||
@HttpWhoisProtocol Protocol httpWhoisProtocol,
|
||||
@WebWhoisProtocol Bootstrap bootstrap,
|
||||
HttpRequestMessage messageTemplate,
|
||||
Duration duration) {
|
||||
|
||||
return ProbingStep.builder()
|
||||
.setProtocol(httpWhoisProtocol)
|
||||
.setBootstrap(bootstrap)
|
||||
.setMessageTemplate(messageTemplate)
|
||||
.setDuration(duration)
|
||||
.build();
|
||||
}
|
||||
|
||||
/** {@link Provides} the {@link Protocol} that corresponds to http connection. */
|
||||
@Singleton
|
||||
@Provides
|
||||
@HttpWhoisProtocol
|
||||
static Protocol provideHttpWhoisProtocol(
|
||||
@HttpWhoisProtocol int httpWhoisPort,
|
||||
@HttpWhoisProtocol ImmutableList<Provider<? extends ChannelHandler>> handlerProviders) {
|
||||
return Protocol.builder()
|
||||
.setName(HTTP_PROTOCOL_NAME)
|
||||
.setPort(httpWhoisPort)
|
||||
.setHandlerProviders(handlerProviders)
|
||||
.setPersistentConnection(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
/** {@link Provides} the {@link Protocol} that corresponds to https connection. */
|
||||
@Singleton
|
||||
@Provides
|
||||
@HttpsWhoisProtocol
|
||||
static Protocol provideHttpsWhoisProtocol(
|
||||
@HttpsWhoisProtocol int httpsWhoisPort,
|
||||
@HttpsWhoisProtocol ImmutableList<Provider<? extends ChannelHandler>> handlerProviders) {
|
||||
return Protocol.builder()
|
||||
.setName(HTTPS_PROTOCOL_NAME)
|
||||
.setPort(httpsWhoisPort)
|
||||
.setHandlerProviders(handlerProviders)
|
||||
.setPersistentConnection(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Provides} the list of providers of {@link ChannelHandler}s that are used for http
|
||||
* protocol.
|
||||
*/
|
||||
@Provides
|
||||
@HttpWhoisProtocol
|
||||
static ImmutableList<Provider<? extends ChannelHandler>> providerHttpWhoisHandlerProviders(
|
||||
Provider<HttpClientCodec> httpClientCodecProvider,
|
||||
Provider<HttpObjectAggregator> httpObjectAggregatorProvider,
|
||||
Provider<WebWhoisMessageHandler> messageHandlerProvider,
|
||||
Provider<WebWhoisActionHandler> webWhoisActionHandlerProvider) {
|
||||
return ImmutableList.of(
|
||||
httpClientCodecProvider,
|
||||
httpObjectAggregatorProvider,
|
||||
messageHandlerProvider,
|
||||
webWhoisActionHandlerProvider);
|
||||
}
|
||||
/**
|
||||
* {@link Provides} the list of providers of {@link ChannelHandler}s that are used for https
|
||||
* protocol.
|
||||
*/
|
||||
@Provides
|
||||
@HttpsWhoisProtocol
|
||||
static ImmutableList<Provider<? extends ChannelHandler>> providerHttpsWhoisHandlerProviders(
|
||||
@HttpsWhoisProtocol
|
||||
Provider<SslClientInitializer<NioSocketChannel>> sslClientInitializerProvider,
|
||||
Provider<HttpClientCodec> httpClientCodecProvider,
|
||||
Provider<HttpObjectAggregator> httpObjectAggregatorProvider,
|
||||
Provider<WebWhoisMessageHandler> messageHandlerProvider,
|
||||
Provider<WebWhoisActionHandler> webWhoisActionHandlerProvider) {
|
||||
return ImmutableList.of(
|
||||
sslClientInitializerProvider,
|
||||
httpClientCodecProvider,
|
||||
httpObjectAggregatorProvider,
|
||||
messageHandlerProvider,
|
||||
webWhoisActionHandlerProvider);
|
||||
}
|
||||
|
||||
@Provides
|
||||
static HttpClientCodec provideHttpClientCodec() {
|
||||
return new HttpClientCodec();
|
||||
}
|
||||
|
||||
@Provides
|
||||
static HttpObjectAggregator provideHttpObjectAggregator(@WebWhoisProtocol int maxContentLength) {
|
||||
return new HttpObjectAggregator(maxContentLength);
|
||||
}
|
||||
|
||||
/** {@link Provides} the {@link SslClientInitializer} used for the {@link HttpsWhoisProtocol}. */
|
||||
@Provides
|
||||
@HttpsWhoisProtocol
|
||||
static SslClientInitializer<NioSocketChannel> provideSslClientInitializer(
|
||||
SslProvider sslProvider) {
|
||||
return createSslClientInitializerWithSystemTrustStore(
|
||||
sslProvider,
|
||||
channel -> channel.attr(REMOTE_ADDRESS_KEY).get(),
|
||||
channel -> channel.attr(PROTOCOL_KEY).get().port());
|
||||
}
|
||||
|
||||
/** {@link Provides} the {@link Bootstrap} used by the WebWhois sequence. */
|
||||
@Singleton
|
||||
@Provides
|
||||
@WebWhoisProtocol
|
||||
static Bootstrap provideBootstrap(
|
||||
EventLoopGroup eventLoopGroup, Class<? extends Channel> channelClazz) {
|
||||
return new Bootstrap().group(eventLoopGroup).channel(channelClazz);
|
||||
}
|
||||
|
||||
/** {@link Provides} standard WebWhois sequence. */
|
||||
@Provides
|
||||
@Singleton
|
||||
@IntoSet
|
||||
ProbingSequence provideWebWhoisSequence(
|
||||
@WebWhoisProtocol ProbingStep probingStep,
|
||||
WebWhoisToken webWhoisToken,
|
||||
MetricsCollector metrics,
|
||||
Clock clock) {
|
||||
return new ProbingSequence.Builder(webWhoisToken, metrics, clock).add(probingStep).build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@WebWhoisProtocol
|
||||
int provideMaximumMessageLengthBytes() {
|
||||
return maximumMessageLengthBytes;
|
||||
}
|
||||
|
||||
/** {@link Provides} the list of top level domains to be probed */
|
||||
@Singleton
|
||||
@Provides
|
||||
@WebWhoisProtocol
|
||||
ImmutableList<String> provideTopLevelDomains() {
|
||||
return ImmutableList.of("how", "soy", "xn--q9jyb4c");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@HttpWhoisProtocol
|
||||
int provideHttpWhoisPort() {
|
||||
return HTTP_WHOIS_PORT;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@HttpsWhoisProtocol
|
||||
int provideHttpsWhoisPort() {
|
||||
return HTTPS_WHOIS_PORT;
|
||||
}
|
||||
|
||||
/** Dagger qualifier to provide HTTP whois protocol related handlers and other bindings. */
|
||||
@Qualifier
|
||||
public @interface HttpWhoisProtocol {}
|
||||
|
||||
/** Dagger qualifier to provide HTTPS whois protocol related handlers and other bindings. */
|
||||
@Qualifier
|
||||
public @interface HttpsWhoisProtocol {}
|
||||
|
||||
/** Dagger qualifier to provide any WebWhois related bindings. */
|
||||
@Qualifier
|
||||
public @interface WebWhoisProtocol {}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.token;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.PeekingIterator;
|
||||
import google.registry.monitoring.blackbox.exception.UndeterminedStateException;
|
||||
import google.registry.monitoring.blackbox.message.OutboundMessageType;
|
||||
import google.registry.monitoring.blackbox.module.WebWhoisModule.WebWhoisProtocol;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
/**
|
||||
* {@link Token} subtype designed for WebWhois sequence.
|
||||
*
|
||||
* <p>Between loops of a WebWhois sequence the only thing changing is the tld we are probing. As a
|
||||
* result, we maintain the list of {@code topLevelDomains} and on each call to next, have our index
|
||||
* looking at the next {@code topLevelDomain}.
|
||||
*/
|
||||
public class WebWhoisToken extends Token {
|
||||
|
||||
/** For each top level domain (tld), we probe "prefix.tld". */
|
||||
private static final String PREFIX = "whois.nic.";
|
||||
|
||||
/** {@link PeekingIterator} over a cycle of all top level domains to be probed. */
|
||||
private final PeekingIterator<String> tldCycleIterator;
|
||||
|
||||
@Inject
|
||||
public WebWhoisToken(@WebWhoisProtocol ImmutableList<String> topLevelDomainsList) {
|
||||
checkArgument(!topLevelDomainsList.isEmpty(), "topLevelDomainsList must not be empty.");
|
||||
|
||||
this.tldCycleIterator =
|
||||
Iterators.peekingIterator(Iterables.cycle(topLevelDomainsList).iterator());
|
||||
}
|
||||
|
||||
/** Moves on to next top level domain in {@code tldCycleIterator}. */
|
||||
@Override
|
||||
public WebWhoisToken next() {
|
||||
tldCycleIterator.next();
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Modifies message to reflect the new host coming from the new top level domain. */
|
||||
@Override
|
||||
public OutboundMessageType modifyMessage(OutboundMessageType original)
|
||||
throws UndeterminedStateException {
|
||||
return original.modifyMessage(host());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns host as the concatenation of fixed {@code prefix} and current value of {@code
|
||||
* topLevelDomains}.
|
||||
*/
|
||||
@Override
|
||||
public String host() {
|
||||
return PREFIX + tldCycleIterator.peek();
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.handler;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.monitoring.blackbox.connection.ProbingAction.CONNECTION_FUTURE_KEY;
|
||||
import static google.registry.monitoring.blackbox.connection.Protocol.PROTOCOL_KEY;
|
||||
import static google.registry.monitoring.blackbox.util.WebWhoisUtils.makeHttpGetRequest;
|
||||
import static google.registry.monitoring.blackbox.util.WebWhoisUtils.makeHttpResponse;
|
||||
import static google.registry.monitoring.blackbox.util.WebWhoisUtils.makeRedirectResponse;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.monitoring.blackbox.connection.Protocol;
|
||||
import google.registry.monitoring.blackbox.exception.FailureException;
|
||||
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
|
||||
import google.registry.monitoring.blackbox.message.HttpResponseMessage;
|
||||
import google.registry.monitoring.blackbox.testserver.TestServer;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import jakarta.inject.Provider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WebWhoisActionHandler}.
|
||||
*
|
||||
* <p>Attempts to test how well {@link WebWhoisActionHandler} works when responding to all possible
|
||||
* types of responses
|
||||
*/
|
||||
class WebWhoisActionHandlerTest {
|
||||
|
||||
private static final int HTTP_PORT = 80;
|
||||
private static final String HTTP_REDIRECT = "http://";
|
||||
private static final String TARGET_HOST = "whois.nic.tld";
|
||||
private static final String DUMMY_URL = "__WILL_NOT_WORK__";
|
||||
private final Protocol standardProtocol =
|
||||
Protocol.builder()
|
||||
.setHandlerProviders(
|
||||
ImmutableList.of(() -> new WebWhoisActionHandler(null, null, null, null)))
|
||||
.setName("http")
|
||||
.setPersistentConnection(false)
|
||||
.setPort(HTTP_PORT)
|
||||
.build();
|
||||
|
||||
private EmbeddedChannel channel;
|
||||
private ActionHandler actionHandler;
|
||||
private Provider<? extends ChannelHandler> actionHandlerProvider;
|
||||
private Protocol initialProtocol;
|
||||
private HttpRequestMessage msg;
|
||||
|
||||
/** Creates default protocol with empty list of handlers and specified other inputs */
|
||||
private Protocol createProtocol(String name, int port, boolean persistentConnection) {
|
||||
return Protocol.builder()
|
||||
.setName(name)
|
||||
.setPort(port)
|
||||
.setHandlerProviders(ImmutableList.of(actionHandlerProvider))
|
||||
.setPersistentConnection(persistentConnection)
|
||||
.build();
|
||||
}
|
||||
|
||||
/** Initializes new WebWhoisActionHandler */
|
||||
private void setupActionHandler(Bootstrap bootstrap, HttpRequestMessage messageTemplate) {
|
||||
actionHandler =
|
||||
new WebWhoisActionHandler(bootstrap, standardProtocol, standardProtocol, messageTemplate);
|
||||
actionHandlerProvider = () -> actionHandler;
|
||||
}
|
||||
|
||||
/** Sets up testing channel with requisite attributes */
|
||||
private void setupChannel(Protocol protocol) {
|
||||
channel = new EmbeddedChannel(actionHandler);
|
||||
channel.attr(PROTOCOL_KEY).set(protocol);
|
||||
channel.attr(CONNECTION_FUTURE_KEY).set(channel.newSucceededFuture());
|
||||
}
|
||||
|
||||
private Bootstrap makeBootstrap(EventLoopGroup group) {
|
||||
return new Bootstrap().group(group).channel(LocalChannel.class);
|
||||
}
|
||||
|
||||
private void setup(String hostName, Bootstrap bootstrap, boolean persistentConnection) {
|
||||
msg = new HttpRequestMessage(makeHttpGetRequest(hostName, ""));
|
||||
setupActionHandler(bootstrap, msg);
|
||||
initialProtocol = createProtocol("testProtocol", 0, persistentConnection);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBasic_responseOk() {
|
||||
// setup
|
||||
setup("", null, true);
|
||||
setupChannel(initialProtocol);
|
||||
|
||||
// stores future
|
||||
ChannelFuture future = actionHandler.getFinishedFuture();
|
||||
channel.writeOutbound(msg);
|
||||
|
||||
FullHttpResponse response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK));
|
||||
|
||||
// assesses that future listener isn't triggered yet.
|
||||
assertThat(future.isDone()).isFalse();
|
||||
|
||||
channel.writeInbound(response);
|
||||
|
||||
// assesses that we successfully received good response and protocol is unchanged
|
||||
assertThat(future.isSuccess()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBasic_responseFailure_badRequest() {
|
||||
// setup
|
||||
setup("", null, false);
|
||||
setupChannel(initialProtocol);
|
||||
|
||||
// Stores future that informs when action is completed.
|
||||
ChannelFuture future = actionHandler.getFinishedFuture();
|
||||
channel.writeOutbound(msg);
|
||||
|
||||
FullHttpResponse response =
|
||||
new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST));
|
||||
|
||||
// Assesses that future listener isn't triggered yet.
|
||||
assertThat(future.isDone()).isFalse();
|
||||
|
||||
channel.writeInbound(response);
|
||||
|
||||
// Assesses that listener is triggered, but event is not success
|
||||
assertThat(future.isDone()).isTrue();
|
||||
assertThat(future.isSuccess()).isFalse();
|
||||
|
||||
// Ensures that we fail as a result of a FailureException.
|
||||
assertThat(future.cause() instanceof FailureException).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBasic_responseFailure_badURL() {
|
||||
// setup
|
||||
setup("", null, false);
|
||||
setupChannel(initialProtocol);
|
||||
|
||||
// stores future
|
||||
ChannelFuture future = actionHandler.getFinishedFuture();
|
||||
channel.writeOutbound(msg);
|
||||
|
||||
FullHttpResponse response =
|
||||
new HttpResponseMessage(
|
||||
makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, DUMMY_URL, true));
|
||||
|
||||
// assesses that future listener isn't triggered yet.
|
||||
assertThat(future.isDone()).isFalse();
|
||||
|
||||
channel.writeInbound(response);
|
||||
|
||||
// assesses that listener is triggered, and event is success
|
||||
assertThat(future.isDone()).isTrue();
|
||||
assertThat(future.isSuccess()).isFalse();
|
||||
|
||||
// Ensures that we fail as a result of a FailureException.
|
||||
assertThat(future.cause()).isInstanceOf(FailureException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAdvanced_redirect() {
|
||||
// Sets up EventLoopGroup with 1 thread to be blocking.
|
||||
EventLoopGroup group = new NioEventLoopGroup(1);
|
||||
|
||||
// Sets up embedded channel.
|
||||
setup("", makeBootstrap(group), false);
|
||||
setupChannel(initialProtocol);
|
||||
|
||||
// Initializes LocalAddress with unique String.
|
||||
LocalAddress address = new LocalAddress(TARGET_HOST);
|
||||
|
||||
// stores future
|
||||
ChannelFuture future = actionHandler.getFinishedFuture();
|
||||
channel.writeOutbound(msg);
|
||||
|
||||
// Path that we test WebWhoisActionHandler uses.
|
||||
String path = "/test";
|
||||
|
||||
// Sets up the local server that the handler will be redirected to.
|
||||
TestServer.webWhoisServer(group, address, "", TARGET_HOST, path);
|
||||
|
||||
FullHttpResponse response =
|
||||
new HttpResponseMessage(
|
||||
makeRedirectResponse(
|
||||
HttpResponseStatus.MOVED_PERMANENTLY, HTTP_REDIRECT + TARGET_HOST + path, true));
|
||||
|
||||
// checks that future has not been set to successful or a failure
|
||||
assertThat(future.isDone()).isFalse();
|
||||
|
||||
channel.writeInbound(response);
|
||||
|
||||
// makes sure old channel is shut down when attempting redirection
|
||||
assertThat(channel.isActive()).isFalse();
|
||||
|
||||
// assesses that we successfully received good response and protocol is unchanged
|
||||
assertThat(future.syncUninterruptibly().isSuccess()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.testserver;
|
||||
|
||||
import static google.registry.monitoring.blackbox.util.WebWhoisUtils.makeHttpResponse;
|
||||
import static google.registry.monitoring.blackbox.util.WebWhoisUtils.makeRedirectResponse;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.monitoring.blackbox.exception.FailureException;
|
||||
import google.registry.monitoring.blackbox.message.EppMessage;
|
||||
import google.registry.monitoring.blackbox.message.HttpResponseMessage;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.local.LocalAddress;
|
||||
import io.netty.channel.local.LocalChannel;
|
||||
import io.netty.channel.local.LocalServerChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.HttpResponse;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
|
||||
/**
|
||||
* Mock Server Superclass whose subclasses implement specific behaviors we expect blackbox server to
|
||||
* perform
|
||||
*/
|
||||
public class TestServer {
|
||||
|
||||
public TestServer(LocalAddress localAddress, ImmutableList<? extends ChannelHandler> handlers) {
|
||||
this(new NioEventLoopGroup(1), localAddress, handlers);
|
||||
}
|
||||
|
||||
private TestServer(
|
||||
EventLoopGroup eventLoopGroup,
|
||||
LocalAddress localAddress,
|
||||
ImmutableList<? extends ChannelHandler> handlers) {
|
||||
// Creates ChannelInitializer with handlers specified
|
||||
ChannelInitializer<LocalChannel> serverInitializer =
|
||||
new ChannelInitializer<>() {
|
||||
@Override
|
||||
protected void initChannel(LocalChannel ch) {
|
||||
for (ChannelHandler handler : handlers) {
|
||||
ch.pipeline().addLast(handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Sets up serverBootstrap with specified initializer, eventLoopGroup, and using
|
||||
// LocalServerChannel class
|
||||
ServerBootstrap serverBootstrap =
|
||||
new ServerBootstrap()
|
||||
.group(eventLoopGroup)
|
||||
.channel(LocalServerChannel.class)
|
||||
.childHandler(serverInitializer);
|
||||
|
||||
ChannelFuture unusedFuture = serverBootstrap.bind(localAddress).syncUninterruptibly();
|
||||
}
|
||||
|
||||
public static TestServer webWhoisServer(
|
||||
EventLoopGroup eventLoopGroup,
|
||||
LocalAddress localAddress,
|
||||
String redirectInput,
|
||||
String destinationInput,
|
||||
String destinationPath) {
|
||||
return new TestServer(
|
||||
eventLoopGroup,
|
||||
localAddress,
|
||||
ImmutableList.of(new RedirectHandler(redirectInput, destinationInput, destinationPath)));
|
||||
}
|
||||
|
||||
public static TestServer eppServer(EventLoopGroup eventLoopGroup, LocalAddress localAddress) {
|
||||
// TODO - add LengthFieldBasedFrameDecoder to handlers in pipeline if necessary for future
|
||||
// tests.
|
||||
return new TestServer(eventLoopGroup, localAddress, ImmutableList.of(new EppHandler()));
|
||||
}
|
||||
|
||||
/** Handler that will wither redirect client, give successful response, or give error messge */
|
||||
@Sharable
|
||||
static class RedirectHandler extends SimpleChannelInboundHandler<HttpRequest> {
|
||||
|
||||
private String redirectInput;
|
||||
private String destinationInput;
|
||||
private String destinationPath;
|
||||
|
||||
/**
|
||||
* @param redirectInput - Server will send back redirect to {@code destinationInput} when
|
||||
* receiving a request with this host location
|
||||
* @param destinationInput - Server will send back an {@link HttpResponseStatus} OK response
|
||||
* when receiving a request with this host location
|
||||
*/
|
||||
RedirectHandler(String redirectInput, String destinationInput, String destinationPath) {
|
||||
this.redirectInput = redirectInput;
|
||||
this.destinationInput = destinationInput;
|
||||
this.destinationPath = destinationPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads input {@link HttpRequest}, and creates appropriate {@link HttpResponseMessage} based on
|
||||
* what header location is
|
||||
*/
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext ctx, HttpRequest request) {
|
||||
HttpResponse response;
|
||||
if (request.headers().get("host").equals(redirectInput)) {
|
||||
response =
|
||||
new HttpResponseMessage(
|
||||
makeRedirectResponse(HttpResponseStatus.MOVED_PERMANENTLY, destinationInput, true));
|
||||
} else if (request.headers().get("host").equals(destinationInput)
|
||||
&& request.uri().equals(destinationPath)) {
|
||||
response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.OK));
|
||||
} else {
|
||||
response = new HttpResponseMessage(makeHttpResponse(HttpResponseStatus.BAD_REQUEST));
|
||||
}
|
||||
ChannelFuture unusedFuture = ctx.channel().writeAndFlush(response);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EppHandler extends ChannelDuplexHandler {
|
||||
|
||||
private ChannelPromise future;
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) {
|
||||
// TODO - pass EppMessage into future to easily read attributes of message.
|
||||
future = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||
ByteBuf buf = (ByteBuf) msg;
|
||||
|
||||
byte[] messageBytes = new byte[buf.readableBytes()];
|
||||
buf.readBytes(messageBytes);
|
||||
|
||||
// TODO - Break ByteBuf into multiple pieces to test how well it works with
|
||||
// LengthFieldBasedFrameDecoder.
|
||||
|
||||
try {
|
||||
EppMessage.byteArrayToXmlDoc(messageBytes);
|
||||
ChannelFuture unusedFuture = future.setSuccess();
|
||||
} catch (FailureException e) {
|
||||
ChannelFuture unusedFuture = future.setFailure(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import io.netty.channel.Channel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/** Unit Tests for each {@link Token} subtype (just {@link WebWhoisToken} for now) */
|
||||
/** Unit Tests for each {@link Token} subtype (just {@link EppToken} for now) */
|
||||
class EppTokenTest {
|
||||
|
||||
private static String TEST_HOST = "host";
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.token;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.monitoring.blackbox.exception.UndeterminedStateException;
|
||||
import google.registry.monitoring.blackbox.message.HttpRequestMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit Tests for {@link WebWhoisToken} */
|
||||
class WebWhoisTokenTest {
|
||||
|
||||
private static final String PREFIX = "whois.nic.";
|
||||
private static final String HOST = "starter";
|
||||
private static final String FIRST_TLD = "first_test";
|
||||
private static final String SECOND_TLD = "second_test";
|
||||
private static final String THIRD_TLD = "third_test";
|
||||
private final ImmutableList<String> testDomains =
|
||||
ImmutableList.of(FIRST_TLD, SECOND_TLD, THIRD_TLD);
|
||||
|
||||
private Token webToken = new WebWhoisToken(testDomains);
|
||||
|
||||
@Test
|
||||
void testMessageModification() throws UndeterminedStateException {
|
||||
// creates Request message with header
|
||||
HttpRequestMessage message = new HttpRequestMessage();
|
||||
message.headers().set("host", HOST);
|
||||
|
||||
// attempts to use Token's method for modifying the method based on its stored host
|
||||
HttpRequestMessage secondMessage = (HttpRequestMessage) webToken.modifyMessage(message);
|
||||
assertThat(secondMessage.headers().get("host")).isEqualTo(PREFIX + FIRST_TLD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHostOfToken() {
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD);
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNextToken() {
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD);
|
||||
webToken = webToken.next();
|
||||
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + SECOND_TLD);
|
||||
webToken = webToken.next();
|
||||
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + THIRD_TLD);
|
||||
webToken = webToken.next();
|
||||
|
||||
assertThat(webToken.host()).isEqualTo(PREFIX + FIRST_TLD);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2019 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.monitoring.blackbox.util;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
|
||||
/** Houses static utility functions for testing WebWHOIS components of Prober. */
|
||||
public class WebWhoisUtils {
|
||||
|
||||
public static FullHttpRequest makeHttpGetRequest(String host, String path) {
|
||||
FullHttpRequest request =
|
||||
new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
|
||||
request.headers().set("host", host).setInt("content-length", 0);
|
||||
return request;
|
||||
}
|
||||
|
||||
public static FullHttpResponse makeHttpResponse(String content, HttpResponseStatus status) {
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(content.getBytes(US_ASCII));
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buf);
|
||||
response.headers().setInt("content-length", buf.readableBytes());
|
||||
return response;
|
||||
}
|
||||
|
||||
public static FullHttpResponse makeHttpResponse(HttpResponseStatus status) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
|
||||
response.headers().setInt("content-length", 0);
|
||||
return response;
|
||||
}
|
||||
|
||||
/** Creates HttpResponse given status, redirection location, and other necessary inputs */
|
||||
public static FullHttpResponse makeRedirectResponse(
|
||||
HttpResponseStatus status, String location, boolean keepAlive) {
|
||||
FullHttpResponse response = makeHttpResponse("", status);
|
||||
response.headers().set("content-type", "text/plain");
|
||||
if (location != null) {
|
||||
response.headers().set("location", location);
|
||||
}
|
||||
if (keepAlive) {
|
||||
response.headers().set("connection", "keep-alive");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user