mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-23 19:20:47 +02:00
Merge pull request #2843 from cisagov/es/2589-rdap-api
2589: RDAP API endpoint [rh]
This commit is contained in:
commit
ab5cd2c9ae
4 changed files with 87 additions and 27 deletions
66
src/api/tests/test_rdap.py
Normal file
66
src/api/tests/test_rdap.py
Normal file
|
@ -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)
|
|
@ -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
|
||||
|
@ -18,7 +18,7 @@ from cachetools.func import ttl_cache
|
|||
from registrar.utility.s3_bucket import S3ClientError, S3ClientHelper
|
||||
|
||||
|
||||
DOMAIN_FILE_URL = "https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv"
|
||||
RDAP_URL = "https://rdap.cloudflareregistry.com/rdap/domain/{domain}"
|
||||
|
||||
|
||||
DOMAIN_API_MESSAGES = {
|
||||
|
@ -41,30 +41,6 @@ DOMAIN_API_MESSAGES = {
|
|||
}
|
||||
|
||||
|
||||
# this file doesn't change that often, nor is it that big, so cache the result
|
||||
# in memory for ten minutes
|
||||
@ttl_cache(ttl=600)
|
||||
def _domains():
|
||||
"""Return a list of the current .gov domains.
|
||||
|
||||
Fetch a file from DOMAIN_FILE_URL, parse the CSV for the domain,
|
||||
lowercase everything and return the list.
|
||||
"""
|
||||
DraftDomain = apps.get_model("registrar.DraftDomain")
|
||||
# 5 second timeout
|
||||
file_contents = requests.get(DOMAIN_FILE_URL, timeout=5).text
|
||||
domains = set()
|
||||
# skip the first line
|
||||
for line in file_contents.splitlines()[1:]:
|
||||
# get the domain before the first comma
|
||||
domain = line.split(",", 1)[0]
|
||||
# sanity-check the string we got from the file here
|
||||
if DraftDomain.string_could_be_domain(domain):
|
||||
# lowercase everything when we put it in domains
|
||||
domains.add(domain.lower())
|
||||
return domains
|
||||
|
||||
|
||||
def check_domain_available(domain):
|
||||
"""Return true if the given domain is available.
|
||||
|
||||
|
@ -99,6 +75,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", "")
|
||||
|
||||
# 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"):
|
||||
|
|
|
@ -32,7 +32,7 @@ from registrar.views.utility.api_views import (
|
|||
)
|
||||
from registrar.views.domains_json import get_domains_json
|
||||
from registrar.views.utility import always_404
|
||||
from api.views import available, get_current_federal, get_current_full
|
||||
from api.views import available, rdap, get_current_federal, get_current_full
|
||||
|
||||
|
||||
DOMAIN_REQUEST_NAMESPACE = views.DomainRequestWizard.URL_NAMESPACE
|
||||
|
@ -194,6 +194,7 @@ urlpatterns = [
|
|||
path("openid/", include("djangooidc.urls")),
|
||||
path("request/", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))),
|
||||
path("api/v1/available/", available, name="available"),
|
||||
path("api/v1/rdap/", rdap, name="rdap"),
|
||||
path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"),
|
||||
path("api/v1/get-report/current-full", get_current_full, name="get-current-full"),
|
||||
path(
|
||||
|
|
|
@ -116,6 +116,7 @@ class TestURLAuth(TestCase):
|
|||
"/api/v1/available/",
|
||||
"/api/v1/get-report/current-federal",
|
||||
"/api/v1/get-report/current-full",
|
||||
"/api/v1/rdap/",
|
||||
"/health",
|
||||
]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue