// Copyright 2017 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.whois; import static google.registry.request.Action.Method.POST; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; import com.google.appengine.api.datastore.DatastoreFailureException; import com.google.appengine.api.datastore.DatastoreTimeoutException; import com.google.common.net.MediaType; import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; import google.registry.request.Response; import google.registry.request.auth.Auth; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.Retrier; import google.registry.whois.WhoisException.UncheckedWhoisException; import google.registry.whois.WhoisMetrics.WhoisMetric; import google.registry.whois.WhoisResponse.WhoisResponseResults; import java.io.Reader; import java.util.concurrent.Callable; import javax.inject.Inject; import org.joda.time.DateTime; /** * HTTP request handler for WHOIS protocol requests sent to us by a proxy. * *
All commands and responses conform to the WHOIS spec as defined in RFC 3912. Commands must be * sent via an HTTP POST in the request body. * *
This servlet is meant to serve as a low level interface for the proxy app which forwards us
* requests received on port 43. However this interface is technically higher level because it sends
* back proper HTTP error codes such as 200, 400, 500, etc. These are discarded by the proxy because
* WHOIS specifies no manner for differentiating successful and erroneous requests.
*
* @see WhoisHttpServer
* @see RFC 3912: WHOIS Protocol Specification
*/
@Action(
path = "/_dr/whois",
method = POST,
auth = Auth.AUTH_INTERNAL_OR_ADMIN
)
public class WhoisServer implements Runnable {
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
/** WHOIS doesn't define an encoding, nor any way to specify an encoding in the protocol. */
static final MediaType CONTENT_TYPE = MediaType.PLAIN_TEXT_UTF_8;
/**
* As stated above, this is the low level interface intended for port 43, and as such, it
* always prefers ASCII.
*/
static final boolean PREFER_UNICODE = false;
@Inject Clock clock;
@Inject Reader input;
@Inject Response response;
@Inject Retrier retrier;
@Inject WhoisReader whoisReader;
@Inject @Config("whoisDisclaimer") String disclaimer;
@Inject WhoisMetric.Builder metricBuilder;
@Inject WhoisMetrics whoisMetrics;
@Inject WhoisServer() {}
@Override
public void run() {
String responseText;
final DateTime now = clock.nowUtc();
try {
final WhoisCommand command = whoisReader.readCommand(input, now);
metricBuilder.setCommand(command);
WhoisResponseResults results =
retrier.callWithRetry(
new Callable