Skip to content

Commit 14989a7

Browse files
committed
Redirect an empty RDAP path to the /help response
The behavior when someone hits the plain RDAP base URL isn't specified by the spec. Currently we just return a plain 404 which isn't particularly nice or helpful -- so it would probably be nicer to just redirect to the /help response instead. tested on alpha, https://pubapi-dot-domain-registry-alpha.appspot.com/rdap redirects to https://pubapi-dot-domain-registry-alpha.appspot.com/rdap/help
1 parent 2d82646 commit 14989a7

File tree

8 files changed

+112
-1
lines changed

8 files changed

+112
-1
lines changed

core/src/main/java/google/registry/env/common/pubapi/WEB-INF/web.xml

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
</servlet-mapping>
2626

2727
<!-- RDAP (new WHOIS). -->
28+
<servlet-mapping>
29+
<servlet-name>pubapi-servlet</servlet-name>
30+
<url-pattern>/rdap</url-pattern>
31+
</servlet-mapping>
2832
<servlet-mapping>
2933
<servlet-name>pubapi-servlet</servlet-name>
3034
<url-pattern>/rdap/*</url-pattern>

core/src/main/java/google/registry/module/RequestComponent.java

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import google.registry.rdap.RdapAutnumAction;
6363
import google.registry.rdap.RdapDomainAction;
6464
import google.registry.rdap.RdapDomainSearchAction;
65+
import google.registry.rdap.RdapEmptyAction;
6566
import google.registry.rdap.RdapEntityAction;
6667
import google.registry.rdap.RdapEntitySearchAction;
6768
import google.registry.rdap.RdapHelpAction;
@@ -261,6 +262,8 @@ interface RequestComponent {
261262

262263
RdapDomainSearchAction rdapDomainSearchAction();
263264

265+
RdapEmptyAction rdapEmptyAction();
266+
264267
RdapEntityAction rdapEntityAction();
265268

266269
RdapEntitySearchAction rdapEntitySearchAction();

core/src/main/java/google/registry/module/pubapi/PubApiRequestComponent.java

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import google.registry.rdap.RdapAutnumAction;
2525
import google.registry.rdap.RdapDomainAction;
2626
import google.registry.rdap.RdapDomainSearchAction;
27+
import google.registry.rdap.RdapEmptyAction;
2728
import google.registry.rdap.RdapEntityAction;
2829
import google.registry.rdap.RdapEntitySearchAction;
2930
import google.registry.rdap.RdapHelpAction;
@@ -55,6 +56,9 @@ public interface PubApiRequestComponent {
5556
RdapAutnumAction rdapAutnumAction();
5657
RdapDomainAction rdapDomainAction();
5758
RdapDomainSearchAction rdapDomainSearchAction();
59+
60+
RdapEmptyAction rdapEmptyAction();
61+
5862
RdapEntityAction rdapEntityAction();
5963
RdapEntitySearchAction rdapEntitySearchAction();
6064
RdapHelpAction rdapHelpAction();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package google.registry.rdap;
16+
17+
import static google.registry.request.Action.Method.GET;
18+
import static google.registry.request.Action.Method.HEAD;
19+
20+
import google.registry.request.Action;
21+
import google.registry.request.Response;
22+
import google.registry.request.auth.Auth;
23+
import jakarta.inject.Inject;
24+
import java.io.IOException;
25+
26+
/**
27+
* RDAP action that serves the empty string, redirecting to the help page.
28+
*
29+
* <p>This isn't technically required, but if someone requests the base url it seems nice to give
30+
* them the help response.
31+
*/
32+
@Action(
33+
service = Action.GaeService.PUBAPI,
34+
path = "/rdap",
35+
method = {GET, HEAD},
36+
auth = Auth.AUTH_PUBLIC)
37+
public class RdapEmptyAction implements Runnable {
38+
39+
private final Response response;
40+
41+
@Inject
42+
public RdapEmptyAction(Response response) {
43+
this.response = response;
44+
}
45+
46+
@Override
47+
public void run() {
48+
try {
49+
response.sendRedirect(RdapHelpAction.PATH);
50+
} catch (IOException e) {
51+
throw new RuntimeException(e);
52+
}
53+
}
54+
}

core/src/main/java/google/registry/rdap/RdapHelpAction.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131
/** RDAP (new WHOIS) action for help requests. */
3232
@Action(
3333
service = GaeService.PUBAPI,
34-
path = "/rdap/help",
34+
path = RdapHelpAction.PATH,
3535
method = {GET, HEAD},
3636
isPrefix = true,
3737
auth = Auth.AUTH_PUBLIC)
3838
public class RdapHelpAction extends RdapActionBase {
3939

40+
public static final String PATH = "/rdap/help";
41+
4042
/** The help path for the RDAP terms of service. */
4143
public static final String TOS_PATH = "/tos";
4244

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2025 The Nomulus Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package google.registry.rdap;
16+
17+
import static com.google.common.truth.Truth.assertThat;
18+
19+
import google.registry.testing.FakeResponse;
20+
import jakarta.servlet.http.HttpServletResponse;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.api.Test;
23+
24+
/** Tests for {@link RdapEmptyAction}. */
25+
public class RdapEmptyActionTest {
26+
27+
private FakeResponse fakeResponse;
28+
private RdapEmptyAction action;
29+
30+
@BeforeEach
31+
void beforeEach() {
32+
fakeResponse = new FakeResponse();
33+
action = new RdapEmptyAction(fakeResponse);
34+
}
35+
36+
@Test
37+
void testRedirect() {
38+
action.run();
39+
assertThat(fakeResponse.getStatus()).isEqualTo(HttpServletResponse.SC_FOUND);
40+
assertThat(fakeResponse.getPayload()).isEqualTo("Redirected to /rdap/help");
41+
}
42+
}

core/src/test/resources/google/registry/module/pubapi/pubapi_routing.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
SERVICE PATH CLASS METHODS OK MIN USER_POLICY
22
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
33
PUBAPI /check CheckApiAction GET n NONE PUBLIC
4+
PUBAPI /rdap RdapEmptyAction GET,HEAD n NONE PUBLIC
45
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
56
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
67
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC

core/src/test/resources/google/registry/module/routing.txt

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ BACKEND /_dr/task/uploadBsaUnavailableNames UploadBsaUnavailable
5656
BACKEND /_dr/task/wipeOutContactHistoryPii WipeOutContactHistoryPiiAction GET n APP ADMIN
5757
PUBAPI /_dr/whois WhoisAction POST n APP ADMIN
5858
PUBAPI /check CheckApiAction GET n NONE PUBLIC
59+
PUBAPI /rdap RdapEmptyAction GET,HEAD n NONE PUBLIC
5960
PUBAPI /rdap/autnum/(*) RdapAutnumAction GET,HEAD n NONE PUBLIC
6061
PUBAPI /rdap/domain/(*) RdapDomainAction GET,HEAD n NONE PUBLIC
6162
PUBAPI /rdap/domains RdapDomainSearchAction GET,HEAD n NONE PUBLIC

0 commit comments

Comments
 (0)