-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2589: RDAP API endpoint [rh] #2843
Changes from 10 commits
2dca24f
3f7dbd5
919fbbf
5439894
23cb568
155e736
a435eb1
d6201fc
a4c4bba
ea4b4e2
2ab29b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
"""Test the domain rdap lookup API.""" | ||
|
||
import json | ||
|
||
from django.contrib.auth import get_user_model | ||
from django.test import RequestFactory | ||
from django.test import TestCase | ||
|
||
from ..views import rdap | ||
|
||
API_BASE_PATH = "/api/v1/rdap/?domain=" | ||
|
||
|
||
class RdapViewTest(TestCase): | ||
"""Test that the RDAP view function works as expected""" | ||
|
||
def setUp(self): | ||
super().setUp() | ||
self.user = get_user_model().objects.create(username="username") | ||
self.factory = RequestFactory() | ||
|
||
def test_rdap_get_no_tld(self): | ||
"""RDAP API successfully fetches RDAP for domain without a TLD""" | ||
request = self.factory.get(API_BASE_PATH + "whitehouse") | ||
request.user = self.user | ||
response = rdap(request, domain="whitehouse") | ||
# contains the right text | ||
self.assertContains(response, "rdap") | ||
# can be parsed into JSON with appropriate keys | ||
response_object = json.loads(response.content) | ||
self.assertIn("rdapConformance", response_object) | ||
|
||
def test_rdap_invalid_domain(self): | ||
"""RDAP API accepts invalid domain queries and returns JSON response | ||
with appropriate error codes""" | ||
request = self.factory.get(API_BASE_PATH + "whitehouse.com") | ||
request.user = self.user | ||
response = rdap(request, domain="whitehouse.com") | ||
|
||
self.assertContains(response, "errorCode") | ||
response_object = json.loads(response.content) | ||
self.assertIn("errorCode", response_object) | ||
|
||
|
||
class RdapAPITest(TestCase): | ||
"""Test that the API can be called as expected.""" | ||
|
||
def setUp(self): | ||
super().setUp() | ||
username = "test_user" | ||
first_name = "First" | ||
last_name = "Last" | ||
email = "info@example.com" | ||
title = "title" | ||
phone = "8080102431" | ||
self.user = get_user_model().objects.create( | ||
username=username, title=title, first_name=first_name, last_name=last_name, email=email, phone=phone | ||
) | ||
|
||
def test_rdap_get(self): | ||
"""Can call RDAP API""" | ||
self.client.force_login(self.user) | ||
response = self.client.get(API_BASE_PATH + "whitehouse.gov") | ||
self.assertContains(response, "rdap") | ||
response_object = json.loads(response.content) | ||
self.assertIn("rdapConformance", response_object) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
|
||
from django.apps import apps | ||
from django.views.decorators.http import require_http_methods | ||
from django.http import HttpResponse | ||
from django.http import HttpResponse, JsonResponse | ||
from django.utils.safestring import mark_safe | ||
|
||
from registrar.templatetags.url_helpers import public_site_url | ||
|
@@ -19,6 +19,7 @@ | |
|
||
|
||
DOMAIN_FILE_URL = "https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you remove this and any uses of this while your in the code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @abroddrick sure! I'm not as familiar with where this is used but is current-full no longer referenced in manage.get.gov? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope it isn't |
||
RDAP_URL = "https://rdap.cloudflareregistry.com/rdap/domain/{domain}" | ||
|
||
|
||
DOMAIN_API_MESSAGES = { | ||
|
@@ -99,6 +100,22 @@ def available(request, domain=""): | |
return json_response | ||
|
||
|
||
@require_http_methods(["GET"]) | ||
@login_not_required | ||
# Since we cache domain RDAP data, cache time may need to be re-evaluated this if we encounter any memory issues | ||
@ttl_cache(ttl=600) | ||
def rdap(request, domain=""): | ||
"""Returns JSON dictionary of a domain's RDAP data from Cloudflare API""" | ||
domain = request.GET.get("domain", "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. overall lgtm! I was just wondering why the ttl is 600 seconds? Is that standard? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think generally 5 minutes is one of the standard defaults for caching which we also use in the availability endpoint! If there ends up being a cache time that makes more sense for this data we can also always update it if the need arises :") There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, LGTM. 600 seconds is 10 minutes. Was that intentional for this cache? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ack you're right, did not math that math correctly :") |
||
|
||
# If inputted domain doesn't have a TLD, append .gov to it | ||
if "." not in domain: | ||
domain = f"{domain}.gov" | ||
|
||
rdap_data = requests.get(RDAP_URL.format(domain=domain), timeout=5).json() | ||
return JsonResponse(rdap_data) | ||
|
||
|
||
@require_http_methods(["GET"]) | ||
@login_not_required | ||
def get_current_full(request, file_name="current-full.csv"): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@abroddrick Since we don't call the RDAP API in any of manage.get.gov's views, I had our tests inherit from TestCase rather than create a mock RDAP library since it would go unused unless we find a reason to add RDAP views into the registrar. I can add a mock RDAP library class if we want to follow availability standards but it will likely go unused until we use RDAP in manage.get.gov and not just get.gov
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense