We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update /availability API to pull from new registry
### Issue Description

The [current API](https://github.com/cisagov/getgov/blob/784cc0f618e056c262512d688e8e4316dd25c9e4/src/api/views.py#L14) consists of a second-hand pull of canonical data that the .gov program [publishes to GitHub](https://github.com/cisagov/dotgov-data/blob/main/current-full.csv). Change this implementation so that queries poll the new registry/Whois/RDAP.

### Acceptance Criteria

- [x] The checkDomain method is used to check that a domain is in the registry or not

and

- [x] The check is used at /availability 
- [x] Tests are implemented and/or updated
- [ ]  In the new domain application flow, where a user is checking if a domain is available for use, it should now use this /availability endpoint (if not already) and tests should be updated to check that /availability and epp is being triggered on this page as well. 

### Additional Context (optional)

Once done, the backend work of #476 and frontend work of #561 can be completed.

_Consider add-on to defend the endpoint from bot spam._

### Implementation Notes

Epp has a check command that can be run with just the name of a given domain.  This should be used as the method for checking the desired domain at this endpoint.

### Issue Links

Blocking #476 and #561
Blocked by #1028 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/api/views.py`
Content:
```
1 """Internal API views"""
2 from django.apps import apps
3 from django.views.decorators.http import require_http_methods
4 from django.http import JsonResponse
5 
6 from django.contrib.auth.decorators import login_required
7 
8 import requests
9 
10 from cachetools.func import ttl_cache
11 
12 
13 DOMAIN_FILE_URL = (
14     "https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv"
15 )
16 
17 
18 DOMAIN_API_MESSAGES = {
19     "required": "Enter the .gov domain you want. Don’t include “www” or “.gov.”"
20     " For example, if you want www.city.gov, you would enter “city”"
21     " (without the quotes).",
22     "extra_dots": "Enter the .gov domain you want without any periods.",
23     "unavailable": "That domain isn’t available. Try entering another one."
24     " Contact us if you need help coming up with a domain.",
25     "invalid": "Enter a domain using only letters,"
26     " numbers, or hyphens (though we don't recommend using hyphens).",
27     "success": "That domain is available!",
28 }
29 
30 
31 # this file doesn't change that often, nor is it that big, so cache the result
32 # in memory for ten minutes
33 @ttl_cache(ttl=600)
34 def _domains():
35     """Return a list of the current .gov domains.
36 
37     Fetch a file from DOMAIN_FILE_URL, parse the CSV for the domain,
38     lowercase everything and return the list.
39     """
40     DraftDomain = apps.get_model("registrar.DraftDomain")
41     # 5 second timeout
42     file_contents = requests.get(DOMAIN_FILE_URL, timeout=5).text
43     domains = set()
44     # skip the first line
45     for line in file_contents.splitlines()[1:]:
46         # get the domain before the first comma
47         domain = line.split(",", 1)[0]
48         # sanity-check the string we got from the file here
49         if DraftDomain.string_could_be_domain(domain):
50             # lowercase everything when we put it in domains
51             domains.add(domain.lower())
52     return domains
53 
54 
55 def in_domains(domain):
56     """Return true if the given domain is in the domains list.
57 
58     The given domain is lowercased to match against the domains list. If the
59     given domain doesn't end with .gov, ".gov" is added when looking for
60     a match.
61     """
62     domain = domain.lower()
63     if domain.endswith(".gov"):
64         return domain.lower() in _domains()
65     else:
66         # domain search string doesn't end with .gov, add it on here
67         return (domain + ".gov") in _domains()
68 
69 
70 @require_http_methods(["GET"])
71 @login_required
72 def available(request, domain=""):
73     """Is a given domain available or not.
74 
75     Response is a JSON dictionary with the key "available" and value true or
76     false.
77     """
78     DraftDomain = apps.get_model("registrar.DraftDomain")
79     # validate that the given domain could be a domain name and fail early if
80     # not.
81     if not (
82         DraftDomain.string_could_be_domain(domain)
83         or DraftDomain.string_could_be_domain(domain + ".gov")
84     ):
85         return JsonResponse(
86             {"available": False, "message": DOMAIN_API_MESSAGES["invalid"]}
87         )
88     # a domain is available if it is NOT in the list of current domains
89     if in_domains(domain):
90         return JsonResponse(
91             {"available": False, "message": DOMAIN_API_MESSAGES["unavailable"]}
92         )
93     else:
94         return JsonResponse(
95             {"available": True, "message": DOMAIN_API_MESSAGES["success"]}
96         )
97
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/api/views.py b/src/api/views.py
--- a/src/api/views.py
+++ b/src/api/views.py
@@ -59,12 +59,12 @@
     given domain doesn't end with .gov, ".gov" is added when looking for
     a match.
     """
-    domain = domain.lower()
+    Domain = apps.get_model("registrar.Domain")
     if domain.endswith(".gov"):
-        return domain.lower() in _domains()
+        return Domain.available(domain)
     else:
         # domain search string doesn't end with .gov, add it on here
-        return (domain + ".gov") in _domains()
+        return Domain.available(domain + ".gov")
 
 
 @require_http_methods(["GET"])

{"golden_diff": "diff --git a/src/api/views.py b/src/api/views.py\n--- a/src/api/views.py\n+++ b/src/api/views.py\n@@ -59,12 +59,12 @@\n     given domain doesn't end with .gov, \".gov\" is added when looking for\n     a match.\n     \"\"\"\n-    domain = domain.lower()\n+    Domain = apps.get_model(\"registrar.Domain\")\n     if domain.endswith(\".gov\"):\n-        return domain.lower() in _domains()\n+        return Domain.available(domain)\n     else:\n         # domain search string doesn't end with .gov, add it on here\n-        return (domain + \".gov\") in _domains()\n+        return Domain.available(domain + \".gov\")\n \n \n @require_http_methods([\"GET\"])\n", "issue": "Update /availability API to pull from new registry\n### Issue Description\r\n\r\nThe [current API](https://github.com/cisagov/getgov/blob/784cc0f618e056c262512d688e8e4316dd25c9e4/src/api/views.py#L14) consists of a second-hand pull of canonical data that the .gov program [publishes to GitHub](https://github.com/cisagov/dotgov-data/blob/main/current-full.csv). Change this implementation so that queries poll the new registry/Whois/RDAP.\r\n\r\n### Acceptance Criteria\r\n\r\n- [x] The checkDomain method is used to check that a domain is in the registry or not\r\n\r\nand\r\n\r\n- [x] The check is used at /availability \r\n- [x] Tests are implemented and/or updated\r\n- [ ]  In the new domain application flow, where a user is checking if a domain is available for use, it should now use this /availability endpoint (if not already) and tests should be updated to check that /availability and epp is being triggered on this page as well. \r\n\r\n### Additional Context (optional)\r\n\r\nOnce done, the backend work of #476 and frontend work of #561 can be completed.\r\n\r\n_Consider add-on to defend the endpoint from bot spam._\r\n\r\n### Implementation Notes\r\n\r\nEpp has a check command that can be run with just the name of a given domain.  This should be used as the method for checking the desired domain at this endpoint.\r\n\r\n### Issue Links\r\n\r\nBlocking #476 and #561\r\nBlocked by #1028 \n", "before_files": [{"content": "\"\"\"Internal API views\"\"\"\nfrom django.apps import apps\nfrom django.views.decorators.http import require_http_methods\nfrom django.http import JsonResponse\n\nfrom django.contrib.auth.decorators import login_required\n\nimport requests\n\nfrom cachetools.func import ttl_cache\n\n\nDOMAIN_FILE_URL = (\n    \"https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv\"\n)\n\n\nDOMAIN_API_MESSAGES = {\n    \"required\": \"Enter the .gov domain you want. Don\u2019t include \u201cwww\u201d or \u201c.gov.\u201d\"\n    \" For example, if you want www.city.gov, you would enter \u201ccity\u201d\"\n    \" (without the quotes).\",\n    \"extra_dots\": \"Enter the .gov domain you want without any periods.\",\n    \"unavailable\": \"That domain isn\u2019t available. Try entering another one.\"\n    \" Contact us if you need help coming up with a domain.\",\n    \"invalid\": \"Enter a domain using only letters,\"\n    \" numbers, or hyphens (though we don't recommend using hyphens).\",\n    \"success\": \"That domain is available!\",\n}\n\n\n# this file doesn't change that often, nor is it that big, so cache the result\n# in memory for ten minutes\n@ttl_cache(ttl=600)\ndef _domains():\n    \"\"\"Return a list of the current .gov domains.\n\n    Fetch a file from DOMAIN_FILE_URL, parse the CSV for the domain,\n    lowercase everything and return the list.\n    \"\"\"\n    DraftDomain = apps.get_model(\"registrar.DraftDomain\")\n    # 5 second timeout\n    file_contents = requests.get(DOMAIN_FILE_URL, timeout=5).text\n    domains = set()\n    # skip the first line\n    for line in file_contents.splitlines()[1:]:\n        # get the domain before the first comma\n        domain = line.split(\",\", 1)[0]\n        # sanity-check the string we got from the file here\n        if DraftDomain.string_could_be_domain(domain):\n            # lowercase everything when we put it in domains\n            domains.add(domain.lower())\n    return domains\n\n\ndef in_domains(domain):\n    \"\"\"Return true if the given domain is in the domains list.\n\n    The given domain is lowercased to match against the domains list. If the\n    given domain doesn't end with .gov, \".gov\" is added when looking for\n    a match.\n    \"\"\"\n    domain = domain.lower()\n    if domain.endswith(\".gov\"):\n        return domain.lower() in _domains()\n    else:\n        # domain search string doesn't end with .gov, add it on here\n        return (domain + \".gov\") in _domains()\n\n\n@require_http_methods([\"GET\"])\n@login_required\ndef available(request, domain=\"\"):\n    \"\"\"Is a given domain available or not.\n\n    Response is a JSON dictionary with the key \"available\" and value true or\n    false.\n    \"\"\"\n    DraftDomain = apps.get_model(\"registrar.DraftDomain\")\n    # validate that the given domain could be a domain name and fail early if\n    # not.\n    if not (\n        DraftDomain.string_could_be_domain(domain)\n        or DraftDomain.string_could_be_domain(domain + \".gov\")\n    ):\n        return JsonResponse(\n            {\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"invalid\"]}\n        )\n    # a domain is available if it is NOT in the list of current domains\n    if in_domains(domain):\n        return JsonResponse(\n            {\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"unavailable\"]}\n        )\n    else:\n        return JsonResponse(\n            {\"available\": True, \"message\": DOMAIN_API_MESSAGES[\"success\"]}\n        )\n", "path": "src/api/views.py"}], "after_files": [{"content": "\"\"\"Internal API views\"\"\"\nfrom django.apps import apps\nfrom django.views.decorators.http import require_http_methods\nfrom django.http import JsonResponse\n\nfrom django.contrib.auth.decorators import login_required\n\nimport requests\n\nfrom cachetools.func import ttl_cache\n\n\nDOMAIN_FILE_URL = (\n    \"https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv\"\n)\n\n\nDOMAIN_API_MESSAGES = {\n    \"required\": \"Enter the .gov domain you want. Don\u2019t include \u201cwww\u201d or \u201c.gov.\u201d\"\n    \" For example, if you want www.city.gov, you would enter \u201ccity\u201d\"\n    \" (without the quotes).\",\n    \"extra_dots\": \"Enter the .gov domain you want without any periods.\",\n    \"unavailable\": \"That domain isn\u2019t available. Try entering another one.\"\n    \" Contact us if you need help coming up with a domain.\",\n    \"invalid\": \"Enter a domain using only letters,\"\n    \" numbers, or hyphens (though we don't recommend using hyphens).\",\n    \"success\": \"That domain is available!\",\n}\n\n\n# this file doesn't change that often, nor is it that big, so cache the result\n# in memory for ten minutes\n@ttl_cache(ttl=600)\ndef _domains():\n    \"\"\"Return a list of the current .gov domains.\n\n    Fetch a file from DOMAIN_FILE_URL, parse the CSV for the domain,\n    lowercase everything and return the list.\n    \"\"\"\n    DraftDomain = apps.get_model(\"registrar.DraftDomain\")\n    # 5 second timeout\n    file_contents = requests.get(DOMAIN_FILE_URL, timeout=5).text\n    domains = set()\n    # skip the first line\n    for line in file_contents.splitlines()[1:]:\n        # get the domain before the first comma\n        domain = line.split(\",\", 1)[0]\n        # sanity-check the string we got from the file here\n        if DraftDomain.string_could_be_domain(domain):\n            # lowercase everything when we put it in domains\n            domains.add(domain.lower())\n    return domains\n\n\ndef in_domains(domain):\n    \"\"\"Return true if the given domain is in the domains list.\n\n    The given domain is lowercased to match against the domains list. If the\n    given domain doesn't end with .gov, \".gov\" is added when looking for\n    a match.\n    \"\"\"\n    Domain = apps.get_model(\"registrar.Domain\")\n    if domain.endswith(\".gov\"):\n        return Domain.available(domain)\n    else:\n        # domain search string doesn't end with .gov, add it on here\n        return Domain.available(domain + \".gov\")\n\n\n@require_http_methods([\"GET\"])\n@login_required\ndef available(request, domain=\"\"):\n    \"\"\"Is a given domain available or not.\n\n    Response is a JSON dictionary with the key \"available\" and value true or\n    false.\n    \"\"\"\n    DraftDomain = apps.get_model(\"registrar.DraftDomain\")\n    # validate that the given domain could be a domain name and fail early if\n    # not.\n    if not (\n        DraftDomain.string_could_be_domain(domain)\n        or DraftDomain.string_could_be_domain(domain + \".gov\")\n    ):\n        return JsonResponse(\n            {\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"invalid\"]}\n        )\n    # a domain is available if it is NOT in the list of current domains\n    if in_domains(domain):\n        return JsonResponse(\n            {\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"unavailable\"]}\n        )\n    else:\n        return JsonResponse(\n            {\"available\": True, \"message\": DOMAIN_API_MESSAGES[\"success\"]}\n        )\n", "path": "src/api/views.py"}]}