We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Subdomain request checking and error presentation
### Story

As a domain applicant, if I'm typing a subdomain on the domain page
I want to be presented with an error
so that I know that I can't submit a subdomain.


### Acceptance Criteria

- [ ] Leverage the existing in page error handling to present the user with content derived from #324 
- [ ] Add a unit test to check validation
- [ ] Submissions should be denied if two dots are present. (Check for the edge case when two "." are not separated by characters:   that state being "..")
- [ ] Submissions should be denied if two dots are present. (Check for the edge case when a "." is at the beginning if the domain without characters in front:   that state being ".something."
- [ ] Confirm other edge cases

### Additional Context

_No response_

### Issue Links

Blocked by: #324
Related to: #720 

--- 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 HttpResponse, JsonResponse
5 from django.utils.safestring import mark_safe
6 
7 from registrar.templatetags.url_helpers import public_site_url
8 from registrar.utility.errors import GenericError, GenericErrorCodes
9 
10 import requests
11 
12 from login_required import login_not_required
13 
14 from cachetools.func import ttl_cache
15 
16 from registrar.utility.s3_bucket import S3ClientError, S3ClientHelper
17 
18 
19 DOMAIN_FILE_URL = "https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv"
20 
21 
22 DOMAIN_API_MESSAGES = {
23     "required": "Enter the .gov domain you want. Don’t include “www” or “.gov.”"
24     " For example, if you want www.city.gov, you would enter “city”"
25     " (without the quotes).",
26     "extra_dots": "Enter the .gov domain you want without any periods.",
27     # message below is considered safe; no user input can be inserted into the message
28     # body; public_site_url() function reads from local app settings and therefore safe
29     "unavailable": mark_safe(  # nosec
30         "That domain isn’t available. "
31         "<a class='usa-link' href='{}' target='_blank'>"
32         "Read more about choosing your .gov domain.</a>".format(public_site_url("domains/choosing"))
33     ),
34     "invalid": "Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens).",
35     "success": "That domain is available!",
36     "error": GenericError.get_error_message(GenericErrorCodes.CANNOT_CONTACT_REGISTRY),
37 }
38 
39 
40 # this file doesn't change that often, nor is it that big, so cache the result
41 # in memory for ten minutes
42 @ttl_cache(ttl=600)
43 def _domains():
44     """Return a list of the current .gov domains.
45 
46     Fetch a file from DOMAIN_FILE_URL, parse the CSV for the domain,
47     lowercase everything and return the list.
48     """
49     DraftDomain = apps.get_model("registrar.DraftDomain")
50     # 5 second timeout
51     file_contents = requests.get(DOMAIN_FILE_URL, timeout=5).text
52     domains = set()
53     # skip the first line
54     for line in file_contents.splitlines()[1:]:
55         # get the domain before the first comma
56         domain = line.split(",", 1)[0]
57         # sanity-check the string we got from the file here
58         if DraftDomain.string_could_be_domain(domain):
59             # lowercase everything when we put it in domains
60             domains.add(domain.lower())
61     return domains
62 
63 
64 def check_domain_available(domain):
65     """Return true if the given domain is available.
66 
67     The given domain is lowercased to match against the domains list. If the
68     given domain doesn't end with .gov, ".gov" is added when looking for
69     a match. If check fails, throws a RegistryError.
70     """
71     Domain = apps.get_model("registrar.Domain")
72     if domain.endswith(".gov"):
73         return Domain.available(domain)
74     else:
75         # domain search string doesn't end with .gov, add it on here
76         return Domain.available(domain + ".gov")
77 
78 
79 @require_http_methods(["GET"])
80 @login_not_required
81 def available(request, domain=""):
82     """Is a given domain available or not.
83 
84     Response is a JSON dictionary with the key "available" and value true or
85     false.
86     """
87     DraftDomain = apps.get_model("registrar.DraftDomain")
88     # validate that the given domain could be a domain name and fail early if
89     # not.
90     if not (DraftDomain.string_could_be_domain(domain) or DraftDomain.string_could_be_domain(domain + ".gov")):
91         return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["invalid"]})
92     # a domain is available if it is NOT in the list of current domains
93     try:
94         if check_domain_available(domain):
95             return JsonResponse({"available": True, "message": DOMAIN_API_MESSAGES["success"]})
96         else:
97             return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["unavailable"]})
98     except Exception:
99         return JsonResponse({"available": False, "message": DOMAIN_API_MESSAGES["error"]})
100 
101 
102 @require_http_methods(["GET"])
103 @login_not_required
104 def get_current_full(request, file_name="current-full.csv"):
105     """This will return the file content of current-full.csv which is the command
106     output of generate_current_full_report.py. This command iterates through each Domain
107     and returns a CSV representation."""
108     return serve_file(file_name)
109 
110 
111 @require_http_methods(["GET"])
112 @login_not_required
113 def get_current_federal(request, file_name="current-federal.csv"):
114     """This will return the file content of current-federal.csv which is the command
115     output of generate_current_federal_report.py. This command iterates through each Domain
116     and returns a CSV representation."""
117     return serve_file(file_name)
118 
119 
120 def serve_file(file_name):
121     """Downloads a file based on a given filepath. Returns a 500 if not found."""
122     s3_client = S3ClientHelper()
123     # Serve the CSV file. If not found, an exception will be thrown.
124     # This will then be caught by flat, causing it to not read it - which is what we want.
125     try:
126         file = s3_client.get_file(file_name, decode_to_utf=True)
127     except S3ClientError as err:
128         # TODO - #1317: Notify operations when auto report generation fails
129         raise err
130 
131     response = HttpResponse(file)
132     return response
133
```

Path: `src/registrar/config/urls.py`
Content:
```
1 """URL Configuration
2 
3 For more information see:
4     https://docs.djangoproject.com/en/4.0/topics/http/urls/
5 """
6 
7 from django.contrib import admin
8 from django.urls import include, path
9 from django.views.generic import RedirectView
10 
11 from registrar import views
12 from registrar.views.application import Step
13 from registrar.views.utility import always_404
14 from api.views import available, get_current_federal, get_current_full
15 
16 
17 APPLICATION_NAMESPACE = views.ApplicationWizard.URL_NAMESPACE
18 application_urls = [
19     path("", views.ApplicationWizard.as_view(), name=""),
20     path("finished/", views.Finished.as_view(), name="finished"),
21 ]
22 
23 # dynamically generate the other application_urls
24 for step, view in [
25     # add/remove steps here
26     (Step.ORGANIZATION_TYPE, views.OrganizationType),
27     (Step.TRIBAL_GOVERNMENT, views.TribalGovernment),
28     (Step.ORGANIZATION_FEDERAL, views.OrganizationFederal),
29     (Step.ORGANIZATION_ELECTION, views.OrganizationElection),
30     (Step.ORGANIZATION_CONTACT, views.OrganizationContact),
31     (Step.ABOUT_YOUR_ORGANIZATION, views.AboutYourOrganization),
32     (Step.AUTHORIZING_OFFICIAL, views.AuthorizingOfficial),
33     (Step.CURRENT_SITES, views.CurrentSites),
34     (Step.DOTGOV_DOMAIN, views.DotgovDomain),
35     (Step.PURPOSE, views.Purpose),
36     (Step.YOUR_CONTACT, views.YourContact),
37     (Step.OTHER_CONTACTS, views.OtherContacts),
38     (Step.NO_OTHER_CONTACTS, views.NoOtherContacts),
39     (Step.ANYTHING_ELSE, views.AnythingElse),
40     (Step.REQUIREMENTS, views.Requirements),
41     (Step.REVIEW, views.Review),
42 ]:
43     application_urls.append(path(f"{step}/", view.as_view(), name=step))
44 
45 
46 urlpatterns = [
47     path("", views.index, name="home"),
48     path(
49         "admin/logout/",
50         RedirectView.as_view(pattern_name="logout", permanent=False),
51     ),
52     path("admin/", admin.site.urls),
53     path(
54         "application/<id>/edit/",
55         views.ApplicationWizard.as_view(),
56         name=views.ApplicationWizard.EDIT_URL_NAME,
57     ),
58     path(
59         "application/<int:pk>",
60         views.ApplicationStatus.as_view(),
61         name="application-status",
62     ),
63     path(
64         "application/<int:pk>/withdraw",
65         views.ApplicationWithdrawConfirmation.as_view(),
66         name="application-withdraw-confirmation",
67     ),
68     path(
69         "application/<int:pk>/withdrawconfirmed",
70         views.ApplicationWithdrawn.as_view(),
71         name="application-withdrawn",
72     ),
73     path("health/", views.health),
74     path("openid/", include("djangooidc.urls")),
75     path("register/", include((application_urls, APPLICATION_NAMESPACE))),
76     path("api/v1/available/<domain>", available, name="available"),
77     path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"),
78     path("api/v1/get-report/current-full", get_current_full, name="get-current-full"),
79     path(
80         "todo",
81         lambda r: always_404(r, "We forgot to include this link, sorry."),
82         name="todo",
83     ),
84     path("domain/<int:pk>", views.DomainView.as_view(), name="domain"),
85     path("domain/<int:pk>/users", views.DomainUsersView.as_view(), name="domain-users"),
86     path(
87         "domain/<int:pk>/dns",
88         views.DomainDNSView.as_view(),
89         name="domain-dns",
90     ),
91     path(
92         "domain/<int:pk>/dns/nameservers",
93         views.DomainNameserversView.as_view(),
94         name="domain-dns-nameservers",
95     ),
96     path(
97         "domain/<int:pk>/dns/dnssec",
98         views.DomainDNSSECView.as_view(),
99         name="domain-dns-dnssec",
100     ),
101     path(
102         "domain/<int:pk>/dns/dnssec/dsdata",
103         views.DomainDsDataView.as_view(),
104         name="domain-dns-dnssec-dsdata",
105     ),
106     path(
107         "domain/<int:pk>/your-contact-information",
108         views.DomainYourContactInformationView.as_view(),
109         name="domain-your-contact-information",
110     ),
111     path(
112         "domain/<int:pk>/org-name-address",
113         views.DomainOrgNameAddressView.as_view(),
114         name="domain-org-name-address",
115     ),
116     path(
117         "domain/<int:pk>/authorizing-official",
118         views.DomainAuthorizingOfficialView.as_view(),
119         name="domain-authorizing-official",
120     ),
121     path(
122         "domain/<int:pk>/security-email",
123         views.DomainSecurityEmailView.as_view(),
124         name="domain-security-email",
125     ),
126     path(
127         "domain/<int:pk>/users/add",
128         views.DomainAddUserView.as_view(),
129         name="domain-users-add",
130     ),
131     path(
132         "invitation/<int:pk>/delete",
133         views.DomainInvitationDeleteView.as_view(http_method_names=["post"]),
134         name="invitation-delete",
135     ),
136 ]
137 
138 # we normally would guard these with `if settings.DEBUG` but tests run with
139 # DEBUG = False even when these apps have been loaded because settings.DEBUG
140 # was actually True. Instead, let's add these URLs any time we are able to
141 # import the debug toolbar package.
142 try:
143     import debug_toolbar  # type: ignore
144 
145     urlpatterns += [path("__debug__/", include(debug_toolbar.urls))]
146 except ImportError:
147     pass
148
```
--- 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
@@ -84,6 +84,7 @@
     Response is a JSON dictionary with the key "available" and value true or
     false.
     """
+    domain = request.GET.get("domain", "")
     DraftDomain = apps.get_model("registrar.DraftDomain")
     # validate that the given domain could be a domain name and fail early if
     # not.
diff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py
--- a/src/registrar/config/urls.py
+++ b/src/registrar/config/urls.py
@@ -73,7 +73,7 @@
     path("health/", views.health),
     path("openid/", include("djangooidc.urls")),
     path("register/", include((application_urls, APPLICATION_NAMESPACE))),
-    path("api/v1/available/<domain>", available, name="available"),
+    path("api/v1/available/", available, name="available"),
     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(

{"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@@ -84,6 +84,7 @@\n     Response is a JSON dictionary with the key \"available\" and value true or\n     false.\n     \"\"\"\n+    domain = request.GET.get(\"domain\", \"\")\n     DraftDomain = apps.get_model(\"registrar.DraftDomain\")\n     # validate that the given domain could be a domain name and fail early if\n     # not.\ndiff --git a/src/registrar/config/urls.py b/src/registrar/config/urls.py\n--- a/src/registrar/config/urls.py\n+++ b/src/registrar/config/urls.py\n@@ -73,7 +73,7 @@\n     path(\"health/\", views.health),\n     path(\"openid/\", include(\"djangooidc.urls\")),\n     path(\"register/\", include((application_urls, APPLICATION_NAMESPACE))),\n-    path(\"api/v1/available/<domain>\", available, name=\"available\"),\n+    path(\"api/v1/available/\", available, name=\"available\"),\n     path(\"api/v1/get-report/current-federal\", get_current_federal, name=\"get-current-federal\"),\n     path(\"api/v1/get-report/current-full\", get_current_full, name=\"get-current-full\"),\n     path(\n", "issue": "Subdomain request checking and error presentation\n### Story\n\nAs a domain applicant, if I'm typing a subdomain on the domain page\nI want to be presented with an error\nso that I know that I can't submit a subdomain.\n\n\n### Acceptance Criteria\n\n- [ ] Leverage the existing in page error handling to present the user with content derived from #324 \n- [ ] Add a unit test to check validation\n- [ ] Submissions should be denied if two dots are present. (Check for the edge case when two \".\" are not separated by characters:   that state being \"..\")\n- [ ] Submissions should be denied if two dots are present. (Check for the edge case when a \".\" is at the beginning if the domain without characters in front:   that state being \".something.\"\n- [ ] Confirm other edge cases\n\n### Additional Context\n\n_No response_\n\n### Issue Links\n\nBlocked by: #324\nRelated to: #720 \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 HttpResponse, JsonResponse\nfrom django.utils.safestring import mark_safe\n\nfrom registrar.templatetags.url_helpers import public_site_url\nfrom registrar.utility.errors import GenericError, GenericErrorCodes\n\nimport requests\n\nfrom login_required import login_not_required\n\nfrom cachetools.func import ttl_cache\n\nfrom registrar.utility.s3_bucket import S3ClientError, S3ClientHelper\n\n\nDOMAIN_FILE_URL = \"https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv\"\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    # message below is considered safe; no user input can be inserted into the message\n    # body; public_site_url() function reads from local app settings and therefore safe\n    \"unavailable\": mark_safe(  # nosec\n        \"That domain isn\u2019t available. \"\n        \"<a class='usa-link' href='{}' target='_blank'>\"\n        \"Read more about choosing your .gov domain.</a>\".format(public_site_url(\"domains/choosing\"))\n    ),\n    \"invalid\": \"Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens).\",\n    \"success\": \"That domain is available!\",\n    \"error\": GenericError.get_error_message(GenericErrorCodes.CANNOT_CONTACT_REGISTRY),\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 check_domain_available(domain):\n    \"\"\"Return true if the given domain is available.\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. If check fails, throws a RegistryError.\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_not_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 (DraftDomain.string_could_be_domain(domain) or DraftDomain.string_could_be_domain(domain + \".gov\")):\n        return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"invalid\"]})\n    # a domain is available if it is NOT in the list of current domains\n    try:\n        if check_domain_available(domain):\n            return JsonResponse({\"available\": True, \"message\": DOMAIN_API_MESSAGES[\"success\"]})\n        else:\n            return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"unavailable\"]})\n    except Exception:\n        return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"error\"]})\n\n\n@require_http_methods([\"GET\"])\n@login_not_required\ndef get_current_full(request, file_name=\"current-full.csv\"):\n    \"\"\"This will return the file content of current-full.csv which is the command\n    output of generate_current_full_report.py. This command iterates through each Domain\n    and returns a CSV representation.\"\"\"\n    return serve_file(file_name)\n\n\n@require_http_methods([\"GET\"])\n@login_not_required\ndef get_current_federal(request, file_name=\"current-federal.csv\"):\n    \"\"\"This will return the file content of current-federal.csv which is the command\n    output of generate_current_federal_report.py. This command iterates through each Domain\n    and returns a CSV representation.\"\"\"\n    return serve_file(file_name)\n\n\ndef serve_file(file_name):\n    \"\"\"Downloads a file based on a given filepath. Returns a 500 if not found.\"\"\"\n    s3_client = S3ClientHelper()\n    # Serve the CSV file. If not found, an exception will be thrown.\n    # This will then be caught by flat, causing it to not read it - which is what we want.\n    try:\n        file = s3_client.get_file(file_name, decode_to_utf=True)\n    except S3ClientError as err:\n        # TODO - #1317: Notify operations when auto report generation fails\n        raise err\n\n    response = HttpResponse(file)\n    return response\n", "path": "src/api/views.py"}, {"content": "\"\"\"URL Configuration\n\nFor more information see:\n    https://docs.djangoproject.com/en/4.0/topics/http/urls/\n\"\"\"\n\nfrom django.contrib import admin\nfrom django.urls import include, path\nfrom django.views.generic import RedirectView\n\nfrom registrar import views\nfrom registrar.views.application import Step\nfrom registrar.views.utility import always_404\nfrom api.views import available, get_current_federal, get_current_full\n\n\nAPPLICATION_NAMESPACE = views.ApplicationWizard.URL_NAMESPACE\napplication_urls = [\n    path(\"\", views.ApplicationWizard.as_view(), name=\"\"),\n    path(\"finished/\", views.Finished.as_view(), name=\"finished\"),\n]\n\n# dynamically generate the other application_urls\nfor step, view in [\n    # add/remove steps here\n    (Step.ORGANIZATION_TYPE, views.OrganizationType),\n    (Step.TRIBAL_GOVERNMENT, views.TribalGovernment),\n    (Step.ORGANIZATION_FEDERAL, views.OrganizationFederal),\n    (Step.ORGANIZATION_ELECTION, views.OrganizationElection),\n    (Step.ORGANIZATION_CONTACT, views.OrganizationContact),\n    (Step.ABOUT_YOUR_ORGANIZATION, views.AboutYourOrganization),\n    (Step.AUTHORIZING_OFFICIAL, views.AuthorizingOfficial),\n    (Step.CURRENT_SITES, views.CurrentSites),\n    (Step.DOTGOV_DOMAIN, views.DotgovDomain),\n    (Step.PURPOSE, views.Purpose),\n    (Step.YOUR_CONTACT, views.YourContact),\n    (Step.OTHER_CONTACTS, views.OtherContacts),\n    (Step.NO_OTHER_CONTACTS, views.NoOtherContacts),\n    (Step.ANYTHING_ELSE, views.AnythingElse),\n    (Step.REQUIREMENTS, views.Requirements),\n    (Step.REVIEW, views.Review),\n]:\n    application_urls.append(path(f\"{step}/\", view.as_view(), name=step))\n\n\nurlpatterns = [\n    path(\"\", views.index, name=\"home\"),\n    path(\n        \"admin/logout/\",\n        RedirectView.as_view(pattern_name=\"logout\", permanent=False),\n    ),\n    path(\"admin/\", admin.site.urls),\n    path(\n        \"application/<id>/edit/\",\n        views.ApplicationWizard.as_view(),\n        name=views.ApplicationWizard.EDIT_URL_NAME,\n    ),\n    path(\n        \"application/<int:pk>\",\n        views.ApplicationStatus.as_view(),\n        name=\"application-status\",\n    ),\n    path(\n        \"application/<int:pk>/withdraw\",\n        views.ApplicationWithdrawConfirmation.as_view(),\n        name=\"application-withdraw-confirmation\",\n    ),\n    path(\n        \"application/<int:pk>/withdrawconfirmed\",\n        views.ApplicationWithdrawn.as_view(),\n        name=\"application-withdrawn\",\n    ),\n    path(\"health/\", views.health),\n    path(\"openid/\", include(\"djangooidc.urls\")),\n    path(\"register/\", include((application_urls, APPLICATION_NAMESPACE))),\n    path(\"api/v1/available/<domain>\", available, name=\"available\"),\n    path(\"api/v1/get-report/current-federal\", get_current_federal, name=\"get-current-federal\"),\n    path(\"api/v1/get-report/current-full\", get_current_full, name=\"get-current-full\"),\n    path(\n        \"todo\",\n        lambda r: always_404(r, \"We forgot to include this link, sorry.\"),\n        name=\"todo\",\n    ),\n    path(\"domain/<int:pk>\", views.DomainView.as_view(), name=\"domain\"),\n    path(\"domain/<int:pk>/users\", views.DomainUsersView.as_view(), name=\"domain-users\"),\n    path(\n        \"domain/<int:pk>/dns\",\n        views.DomainDNSView.as_view(),\n        name=\"domain-dns\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/nameservers\",\n        views.DomainNameserversView.as_view(),\n        name=\"domain-dns-nameservers\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/dnssec\",\n        views.DomainDNSSECView.as_view(),\n        name=\"domain-dns-dnssec\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/dnssec/dsdata\",\n        views.DomainDsDataView.as_view(),\n        name=\"domain-dns-dnssec-dsdata\",\n    ),\n    path(\n        \"domain/<int:pk>/your-contact-information\",\n        views.DomainYourContactInformationView.as_view(),\n        name=\"domain-your-contact-information\",\n    ),\n    path(\n        \"domain/<int:pk>/org-name-address\",\n        views.DomainOrgNameAddressView.as_view(),\n        name=\"domain-org-name-address\",\n    ),\n    path(\n        \"domain/<int:pk>/authorizing-official\",\n        views.DomainAuthorizingOfficialView.as_view(),\n        name=\"domain-authorizing-official\",\n    ),\n    path(\n        \"domain/<int:pk>/security-email\",\n        views.DomainSecurityEmailView.as_view(),\n        name=\"domain-security-email\",\n    ),\n    path(\n        \"domain/<int:pk>/users/add\",\n        views.DomainAddUserView.as_view(),\n        name=\"domain-users-add\",\n    ),\n    path(\n        \"invitation/<int:pk>/delete\",\n        views.DomainInvitationDeleteView.as_view(http_method_names=[\"post\"]),\n        name=\"invitation-delete\",\n    ),\n]\n\n# we normally would guard these with `if settings.DEBUG` but tests run with\n# DEBUG = False even when these apps have been loaded because settings.DEBUG\n# was actually True. Instead, let's add these URLs any time we are able to\n# import the debug toolbar package.\ntry:\n    import debug_toolbar  # type: ignore\n\n    urlpatterns += [path(\"__debug__/\", include(debug_toolbar.urls))]\nexcept ImportError:\n    pass\n", "path": "src/registrar/config/urls.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 HttpResponse, JsonResponse\nfrom django.utils.safestring import mark_safe\n\nfrom registrar.templatetags.url_helpers import public_site_url\nfrom registrar.utility.errors import GenericError, GenericErrorCodes\n\nimport requests\n\nfrom login_required import login_not_required\n\nfrom cachetools.func import ttl_cache\n\nfrom registrar.utility.s3_bucket import S3ClientError, S3ClientHelper\n\n\nDOMAIN_FILE_URL = \"https://raw.githubusercontent.com/cisagov/dotgov-data/main/current-full.csv\"\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    # message below is considered safe; no user input can be inserted into the message\n    # body; public_site_url() function reads from local app settings and therefore safe\n    \"unavailable\": mark_safe(  # nosec\n        \"That domain isn\u2019t available. \"\n        \"<a class='usa-link' href='{}' target='_blank'>\"\n        \"Read more about choosing your .gov domain.</a>\".format(public_site_url(\"domains/choosing\"))\n    ),\n    \"invalid\": \"Enter a domain using only letters, numbers, or hyphens (though we don't recommend using hyphens).\",\n    \"success\": \"That domain is available!\",\n    \"error\": GenericError.get_error_message(GenericErrorCodes.CANNOT_CONTACT_REGISTRY),\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 check_domain_available(domain):\n    \"\"\"Return true if the given domain is available.\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. If check fails, throws a RegistryError.\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_not_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    domain = request.GET.get(\"domain\", \"\")\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 (DraftDomain.string_could_be_domain(domain) or DraftDomain.string_could_be_domain(domain + \".gov\")):\n        return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"invalid\"]})\n    # a domain is available if it is NOT in the list of current domains\n    try:\n        if check_domain_available(domain):\n            return JsonResponse({\"available\": True, \"message\": DOMAIN_API_MESSAGES[\"success\"]})\n        else:\n            return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"unavailable\"]})\n    except Exception:\n        return JsonResponse({\"available\": False, \"message\": DOMAIN_API_MESSAGES[\"error\"]})\n\n\n@require_http_methods([\"GET\"])\n@login_not_required\ndef get_current_full(request, file_name=\"current-full.csv\"):\n    \"\"\"This will return the file content of current-full.csv which is the command\n    output of generate_current_full_report.py. This command iterates through each Domain\n    and returns a CSV representation.\"\"\"\n    return serve_file(file_name)\n\n\n@require_http_methods([\"GET\"])\n@login_not_required\ndef get_current_federal(request, file_name=\"current-federal.csv\"):\n    \"\"\"This will return the file content of current-federal.csv which is the command\n    output of generate_current_federal_report.py. This command iterates through each Domain\n    and returns a CSV representation.\"\"\"\n    return serve_file(file_name)\n\n\ndef serve_file(file_name):\n    \"\"\"Downloads a file based on a given filepath. Returns a 500 if not found.\"\"\"\n    s3_client = S3ClientHelper()\n    # Serve the CSV file. If not found, an exception will be thrown.\n    # This will then be caught by flat, causing it to not read it - which is what we want.\n    try:\n        file = s3_client.get_file(file_name, decode_to_utf=True)\n    except S3ClientError as err:\n        # TODO - #1317: Notify operations when auto report generation fails\n        raise err\n\n    response = HttpResponse(file)\n    return response\n", "path": "src/api/views.py"}, {"content": "\"\"\"URL Configuration\n\nFor more information see:\n    https://docs.djangoproject.com/en/4.0/topics/http/urls/\n\"\"\"\n\nfrom django.contrib import admin\nfrom django.urls import include, path\nfrom django.views.generic import RedirectView\n\nfrom registrar import views\nfrom registrar.views.application import Step\nfrom registrar.views.utility import always_404\nfrom api.views import available, get_current_federal, get_current_full\n\n\nAPPLICATION_NAMESPACE = views.ApplicationWizard.URL_NAMESPACE\napplication_urls = [\n    path(\"\", views.ApplicationWizard.as_view(), name=\"\"),\n    path(\"finished/\", views.Finished.as_view(), name=\"finished\"),\n]\n\n# dynamically generate the other application_urls\nfor step, view in [\n    # add/remove steps here\n    (Step.ORGANIZATION_TYPE, views.OrganizationType),\n    (Step.TRIBAL_GOVERNMENT, views.TribalGovernment),\n    (Step.ORGANIZATION_FEDERAL, views.OrganizationFederal),\n    (Step.ORGANIZATION_ELECTION, views.OrganizationElection),\n    (Step.ORGANIZATION_CONTACT, views.OrganizationContact),\n    (Step.ABOUT_YOUR_ORGANIZATION, views.AboutYourOrganization),\n    (Step.AUTHORIZING_OFFICIAL, views.AuthorizingOfficial),\n    (Step.CURRENT_SITES, views.CurrentSites),\n    (Step.DOTGOV_DOMAIN, views.DotgovDomain),\n    (Step.PURPOSE, views.Purpose),\n    (Step.YOUR_CONTACT, views.YourContact),\n    (Step.OTHER_CONTACTS, views.OtherContacts),\n    (Step.NO_OTHER_CONTACTS, views.NoOtherContacts),\n    (Step.ANYTHING_ELSE, views.AnythingElse),\n    (Step.REQUIREMENTS, views.Requirements),\n    (Step.REVIEW, views.Review),\n]:\n    application_urls.append(path(f\"{step}/\", view.as_view(), name=step))\n\n\nurlpatterns = [\n    path(\"\", views.index, name=\"home\"),\n    path(\n        \"admin/logout/\",\n        RedirectView.as_view(pattern_name=\"logout\", permanent=False),\n    ),\n    path(\"admin/\", admin.site.urls),\n    path(\n        \"application/<id>/edit/\",\n        views.ApplicationWizard.as_view(),\n        name=views.ApplicationWizard.EDIT_URL_NAME,\n    ),\n    path(\n        \"application/<int:pk>\",\n        views.ApplicationStatus.as_view(),\n        name=\"application-status\",\n    ),\n    path(\n        \"application/<int:pk>/withdraw\",\n        views.ApplicationWithdrawConfirmation.as_view(),\n        name=\"application-withdraw-confirmation\",\n    ),\n    path(\n        \"application/<int:pk>/withdrawconfirmed\",\n        views.ApplicationWithdrawn.as_view(),\n        name=\"application-withdrawn\",\n    ),\n    path(\"health/\", views.health),\n    path(\"openid/\", include(\"djangooidc.urls\")),\n    path(\"register/\", include((application_urls, APPLICATION_NAMESPACE))),\n    path(\"api/v1/available/\", available, name=\"available\"),\n    path(\"api/v1/get-report/current-federal\", get_current_federal, name=\"get-current-federal\"),\n    path(\"api/v1/get-report/current-full\", get_current_full, name=\"get-current-full\"),\n    path(\n        \"todo\",\n        lambda r: always_404(r, \"We forgot to include this link, sorry.\"),\n        name=\"todo\",\n    ),\n    path(\"domain/<int:pk>\", views.DomainView.as_view(), name=\"domain\"),\n    path(\"domain/<int:pk>/users\", views.DomainUsersView.as_view(), name=\"domain-users\"),\n    path(\n        \"domain/<int:pk>/dns\",\n        views.DomainDNSView.as_view(),\n        name=\"domain-dns\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/nameservers\",\n        views.DomainNameserversView.as_view(),\n        name=\"domain-dns-nameservers\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/dnssec\",\n        views.DomainDNSSECView.as_view(),\n        name=\"domain-dns-dnssec\",\n    ),\n    path(\n        \"domain/<int:pk>/dns/dnssec/dsdata\",\n        views.DomainDsDataView.as_view(),\n        name=\"domain-dns-dnssec-dsdata\",\n    ),\n    path(\n        \"domain/<int:pk>/your-contact-information\",\n        views.DomainYourContactInformationView.as_view(),\n        name=\"domain-your-contact-information\",\n    ),\n    path(\n        \"domain/<int:pk>/org-name-address\",\n        views.DomainOrgNameAddressView.as_view(),\n        name=\"domain-org-name-address\",\n    ),\n    path(\n        \"domain/<int:pk>/authorizing-official\",\n        views.DomainAuthorizingOfficialView.as_view(),\n        name=\"domain-authorizing-official\",\n    ),\n    path(\n        \"domain/<int:pk>/security-email\",\n        views.DomainSecurityEmailView.as_view(),\n        name=\"domain-security-email\",\n    ),\n    path(\n        \"domain/<int:pk>/users/add\",\n        views.DomainAddUserView.as_view(),\n        name=\"domain-users-add\",\n    ),\n    path(\n        \"invitation/<int:pk>/delete\",\n        views.DomainInvitationDeleteView.as_view(http_method_names=[\"post\"]),\n        name=\"invitation-delete\",\n    ),\n]\n\n# we normally would guard these with `if settings.DEBUG` but tests run with\n# DEBUG = False even when these apps have been loaded because settings.DEBUG\n# was actually True. Instead, let's add these URLs any time we are able to\n# import the debug toolbar package.\ntry:\n    import debug_toolbar  # type: ignore\n\n    urlpatterns += [path(\"__debug__/\", include(debug_toolbar.urls))]\nexcept ImportError:\n    pass\n", "path": "src/registrar/config/urls.py"}]}