We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add a "shortlink" for projects
**From user testing:**

When viewing projects on PyPI, some users type the URL directly if they know the project name.

We should create a shortlink like`pypi.org/p/myproject` which would redirect to `pypi.org/projects/myproject`

cc @di for feedback / guidance.

---

**Good First Issue**: This issue is good for first time contributors. If you've already contributed to Warehouse, please work on [another issue without this label](https://github.com/pypa/warehouse/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3A%22good+first+issue%22) instead. If there is not a corresponding pull request for this issue, it is up for grabs. For directions for getting set up, see our [Getting Started Guide](https://warehouse.pypa.io/development/getting-started/). If you are working on this issue and have questions, please feel free to ask them here, [`#pypa-dev` on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or the [pypa-dev mailing list](https://groups.google.com/forum/#!forum/pypa-dev).


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `warehouse/routes.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12 
13 
14 def includeme(config):
15     # We need to get the value of the Warehouse and Forklift domains, we'll use
16     # these to segregate the Warehouse routes from the Forklift routes until
17     # Forklift is properly split out into it's own project.
18     warehouse = config.get_settings().get("warehouse.domain")
19     files_url = config.get_settings()["files.url"]
20 
21     # Simple Route for health checks.
22     config.add_route("health", "/_health/")
23 
24     # Internal route to make it easier to force a particular status for
25     # debugging HTTPException templates.
26     config.add_route("force-status", "/_force-status/{status:[45]\d\d}/")
27 
28     # Basic global routes
29     config.add_route("index", "/", domain=warehouse)
30     config.add_route("robots.txt", "/robots.txt", domain=warehouse)
31     config.add_route("opensearch.xml", "/opensearch.xml", domain=warehouse)
32     config.add_route("index.sitemap.xml", "/sitemap.xml", domain=warehouse)
33     config.add_route(
34         "bucket.sitemap.xml",
35         "/{bucket}.sitemap.xml",
36         domain=warehouse,
37     )
38 
39     # Some static, template driven pages
40     config.add_template_view("help", "/help/", "pages/help.html")
41     config.add_template_view("security", "/security/", "pages/security.html")
42     config.add_template_view(
43         "sponsors",
44         "/sponsors/",
45         # Use the full resource path here to make it able to be overridden by
46         # pypi-theme.
47         "warehouse:templates/pages/sponsors.html",
48     )
49 
50     # Our legal policies
51     config.add_policy("terms-of-use", "terms.md")
52 
53     # HTML Snippets for including into other pages.
54     config.add_route(
55         "includes.current-user-indicator",
56         "/_includes/current-user-indicator/",
57         domain=warehouse,
58     )
59     config.add_route(
60         "includes.flash-messages",
61         "/_includes/flash-messages/",
62         domain=warehouse,
63     )
64     config.add_route(
65         "includes.current-user-profile-callout",
66         "/_includes/current-user-profile-callout/{username}",
67         factory="warehouse.accounts.models:UserFactory",
68         traverse="/{username}",
69         domain=warehouse,
70     )
71     config.add_route(
72         "includes.edit-project-button",
73         "/_includes/edit-project-button/{project_name}",
74         factory="warehouse.packaging.models:ProjectFactory",
75         traverse="/{project_name}",
76         domain=warehouse,
77     )
78     config.add_route(
79         "includes.edit-profile-button",
80         "/_includes/edit-profile-button/{username}",
81         factory="warehouse.accounts.models:UserFactory",
82         traverse="/{username}",
83         domain=warehouse,
84     )
85 
86     # Search Routes
87     config.add_route("search", "/search/", domain=warehouse)
88 
89     # Accounts
90     config.add_route(
91         "accounts.profile",
92         "/user/{username}/",
93         factory="warehouse.accounts.models:UserFactory",
94         traverse="/{username}",
95         domain=warehouse,
96     )
97     config.add_route("accounts.login", "/account/login/", domain=warehouse)
98     config.add_route("accounts.logout", "/account/logout/", domain=warehouse)
99     config.add_route(
100         "accounts.register",
101         "/account/register/",
102         domain=warehouse,
103     )
104     config.add_route(
105         "accounts.request-password-reset",
106         "/account/request-password-reset/",
107         domain=warehouse,
108     )
109     config.add_route(
110         "accounts.reset-password",
111         "/account/reset-password/",
112         domain=warehouse,
113     )
114     config.add_route(
115         "accounts.verify-email",
116         "/account/verify-email/",
117         domain=warehouse,
118     )
119 
120     # Management (views for logged-in users)
121     config.add_route("manage.account", "/manage/account/", domain=warehouse)
122     config.add_route("manage.projects", "/manage/projects/", domain=warehouse)
123     config.add_route(
124         "manage.project.settings",
125         "/manage/project/{project_name}/settings/",
126         factory="warehouse.packaging.models:ProjectFactory",
127         traverse="/{project_name}",
128         domain=warehouse,
129     )
130     config.add_route(
131         "manage.project.delete_project",
132         "/manage/project/{project_name}/delete_project/",
133         factory="warehouse.packaging.models:ProjectFactory",
134         traverse="/{project_name}",
135         domain=warehouse,
136     )
137     config.add_route(
138         "manage.project.releases",
139         "/manage/project/{project_name}/releases/",
140         factory="warehouse.packaging.models:ProjectFactory",
141         traverse="/{project_name}",
142         domain=warehouse,
143     )
144     config.add_route(
145         "manage.project.release",
146         "/manage/project/{project_name}/release/{version}/",
147         factory="warehouse.packaging.models:ProjectFactory",
148         traverse="/{project_name}/{version}",
149         domain=warehouse,
150     )
151     config.add_route(
152         "manage.project.roles",
153         "/manage/project/{project_name}/collaboration/",
154         factory="warehouse.packaging.models:ProjectFactory",
155         traverse="/{project_name}",
156         domain=warehouse,
157     )
158     config.add_route(
159         "manage.project.change_role",
160         "/manage/project/{project_name}/collaboration/change/",
161         factory="warehouse.packaging.models:ProjectFactory",
162         traverse="/{project_name}",
163         domain=warehouse,
164     )
165     config.add_route(
166         "manage.project.delete_role",
167         "/manage/project/{project_name}/collaboration/delete/",
168         factory="warehouse.packaging.models:ProjectFactory",
169         traverse="/{project_name}",
170         domain=warehouse,
171     )
172     config.add_route(
173         "manage.project.history",
174         "/manage/project/{project_name}/history/",
175         factory="warehouse.packaging.models:ProjectFactory",
176         traverse="/{project_name}",
177         domain=warehouse,
178     )
179 
180     # Packaging
181     config.add_route(
182         "packaging.project",
183         "/project/{name}/",
184         factory="warehouse.packaging.models:ProjectFactory",
185         traverse="/{name}",
186         domain=warehouse,
187     )
188     config.add_route(
189         "packaging.release",
190         "/project/{name}/{version}/",
191         factory="warehouse.packaging.models:ProjectFactory",
192         traverse="/{name}/{version}",
193         domain=warehouse,
194     )
195     config.add_route("packaging.file", files_url)
196 
197     # RSS
198     config.add_route("rss.updates", "/rss/updates.xml", domain=warehouse)
199     config.add_route("rss.packages", "/rss/packages.xml", domain=warehouse)
200 
201     # Legacy URLs
202     config.add_route("legacy.api.simple.index", "/simple/", domain=warehouse)
203     config.add_route(
204         "legacy.api.simple.detail",
205         "/simple/{name}/",
206         factory="warehouse.packaging.models:ProjectFactory",
207         traverse="/{name}/",
208         read_only=True,
209         domain=warehouse,
210     )
211     config.add_route(
212         "legacy.api.json.project",
213         "/pypi/{name}/json",
214         factory="warehouse.packaging.models:ProjectFactory",
215         traverse="/{name}",
216         read_only=True,
217         domain=warehouse,
218     )
219     config.add_route(
220         "legacy.api.json.release",
221         "/pypi/{name}/{version}/json",
222         factory="warehouse.packaging.models:ProjectFactory",
223         traverse="/{name}/{version}",
224         read_only=True,
225         domain=warehouse,
226     )
227 
228     # Legacy Action URLs
229     # TODO: We should probably add Warehouse routes for these that just error
230     #       and direct people to use upload.pypi.io
231     config.add_pypi_action_route(
232         "legacy.api.pypi.file_upload",
233         "file_upload",
234         domain=warehouse,
235     )
236     config.add_pypi_action_route(
237         "legacy.api.pypi.submit",
238         "submit",
239         domain=warehouse,
240     )
241     config.add_pypi_action_route(
242         "legacy.api.pypi.submit_pkg_info",
243         "submit_pkg_info",
244         domain=warehouse,
245     )
246     config.add_pypi_action_route(
247         "legacy.api.pypi.doc_upload",
248         "doc_upload",
249         domain=warehouse,
250     )
251     config.add_pypi_action_route(
252         "legacy.api.pypi.doap",
253         "doap",
254         domain=warehouse,
255     )
256     config.add_pypi_action_route(
257         "legacy.api.pypi.list_classifiers",
258         "list_classifiers",
259         domain=warehouse,
260     )
261 
262     # Legacy XMLRPC
263     config.add_xmlrpc_endpoint(
264         "pypi",
265         pattern="/pypi",
266         header="Content-Type:text/xml",
267         domain=warehouse,
268     )
269 
270     # Legacy Documentation
271     config.add_route("legacy.docs", config.registry.settings["docs.url"])
272 
273     # Legacy Redirects
274     config.add_redirect("/pypi/{name}/", "/project/{name}/", domain=warehouse)
275     config.add_redirect(
276         "/pypi/{name}/{version}/",
277         "/project/{name}/{version}/",
278         domain=warehouse,
279     )
280     config.add_redirect("/packages/{path:.*}", files_url, domain=warehouse)
281 
282     # Legacy Action Redirects
283     config.add_pypi_action_redirect(
284         "rss",
285         "/rss/updates.xml",
286         domain=warehouse,
287     )
288     config.add_pypi_action_redirect(
289         "packages_rss",
290         "/rss/packages.xml",
291         domain=warehouse,
292     )
293
```
--- 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/warehouse/routes.py b/warehouse/routes.py
--- a/warehouse/routes.py
+++ b/warehouse/routes.py
@@ -178,6 +178,7 @@
     )
 
     # Packaging
+    config.add_redirect('/p/{name}/', '/project/{name}/', domain=warehouse)
     config.add_route(
         "packaging.project",
         "/project/{name}/",

{"golden_diff": "diff --git a/warehouse/routes.py b/warehouse/routes.py\n--- a/warehouse/routes.py\n+++ b/warehouse/routes.py\n@@ -178,6 +178,7 @@\n     )\n \n     # Packaging\n+    config.add_redirect('/p/{name}/', '/project/{name}/', domain=warehouse)\n     config.add_route(\n         \"packaging.project\",\n         \"/project/{name}/\",\n", "issue": "Add a \"shortlink\" for projects\n**From user testing:**\r\n\r\nWhen viewing projects on PyPI, some users type the URL directly if they know the project name.\r\n\r\nWe should create a shortlink like`pypi.org/p/myproject` which would redirect to `pypi.org/projects/myproject`\r\n\r\ncc @di for feedback / guidance.\r\n\r\n---\r\n\r\n**Good First Issue**: This issue is good for first time contributors. If you've already contributed to Warehouse, please work on [another issue without this label](https://github.com/pypa/warehouse/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3A%22good+first+issue%22) instead. If there is not a corresponding pull request for this issue, it is up for grabs. For directions for getting set up, see our [Getting Started Guide](https://warehouse.pypa.io/development/getting-started/). If you are working on this issue and have questions, please feel free to ask them here, [`#pypa-dev` on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or the [pypa-dev mailing list](https://groups.google.com/forum/#!forum/pypa-dev).\r\n\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\ndef includeme(config):\n    # We need to get the value of the Warehouse and Forklift domains, we'll use\n    # these to segregate the Warehouse routes from the Forklift routes until\n    # Forklift is properly split out into it's own project.\n    warehouse = config.get_settings().get(\"warehouse.domain\")\n    files_url = config.get_settings()[\"files.url\"]\n\n    # Simple Route for health checks.\n    config.add_route(\"health\", \"/_health/\")\n\n    # Internal route to make it easier to force a particular status for\n    # debugging HTTPException templates.\n    config.add_route(\"force-status\", \"/_force-status/{status:[45]\\d\\d}/\")\n\n    # Basic global routes\n    config.add_route(\"index\", \"/\", domain=warehouse)\n    config.add_route(\"robots.txt\", \"/robots.txt\", domain=warehouse)\n    config.add_route(\"opensearch.xml\", \"/opensearch.xml\", domain=warehouse)\n    config.add_route(\"index.sitemap.xml\", \"/sitemap.xml\", domain=warehouse)\n    config.add_route(\n        \"bucket.sitemap.xml\",\n        \"/{bucket}.sitemap.xml\",\n        domain=warehouse,\n    )\n\n    # Some static, template driven pages\n    config.add_template_view(\"help\", \"/help/\", \"pages/help.html\")\n    config.add_template_view(\"security\", \"/security/\", \"pages/security.html\")\n    config.add_template_view(\n        \"sponsors\",\n        \"/sponsors/\",\n        # Use the full resource path here to make it able to be overridden by\n        # pypi-theme.\n        \"warehouse:templates/pages/sponsors.html\",\n    )\n\n    # Our legal policies\n    config.add_policy(\"terms-of-use\", \"terms.md\")\n\n    # HTML Snippets for including into other pages.\n    config.add_route(\n        \"includes.current-user-indicator\",\n        \"/_includes/current-user-indicator/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.flash-messages\",\n        \"/_includes/flash-messages/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.current-user-profile-callout\",\n        \"/_includes/current-user-profile-callout/{username}\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.edit-project-button\",\n        \"/_includes/edit-project-button/{project_name}\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.edit-profile-button\",\n        \"/_includes/edit-profile-button/{username}\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n\n    # Search Routes\n    config.add_route(\"search\", \"/search/\", domain=warehouse)\n\n    # Accounts\n    config.add_route(\n        \"accounts.profile\",\n        \"/user/{username}/\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n    config.add_route(\"accounts.login\", \"/account/login/\", domain=warehouse)\n    config.add_route(\"accounts.logout\", \"/account/logout/\", domain=warehouse)\n    config.add_route(\n        \"accounts.register\",\n        \"/account/register/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.request-password-reset\",\n        \"/account/request-password-reset/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.reset-password\",\n        \"/account/reset-password/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.verify-email\",\n        \"/account/verify-email/\",\n        domain=warehouse,\n    )\n\n    # Management (views for logged-in users)\n    config.add_route(\"manage.account\", \"/manage/account/\", domain=warehouse)\n    config.add_route(\"manage.projects\", \"/manage/projects/\", domain=warehouse)\n    config.add_route(\n        \"manage.project.settings\",\n        \"/manage/project/{project_name}/settings/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.delete_project\",\n        \"/manage/project/{project_name}/delete_project/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.releases\",\n        \"/manage/project/{project_name}/releases/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.release\",\n        \"/manage/project/{project_name}/release/{version}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}/{version}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.roles\",\n        \"/manage/project/{project_name}/collaboration/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.change_role\",\n        \"/manage/project/{project_name}/collaboration/change/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.delete_role\",\n        \"/manage/project/{project_name}/collaboration/delete/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.history\",\n        \"/manage/project/{project_name}/history/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n\n    # Packaging\n    config.add_route(\n        \"packaging.project\",\n        \"/project/{name}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"packaging.release\",\n        \"/project/{name}/{version}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/{version}\",\n        domain=warehouse,\n    )\n    config.add_route(\"packaging.file\", files_url)\n\n    # RSS\n    config.add_route(\"rss.updates\", \"/rss/updates.xml\", domain=warehouse)\n    config.add_route(\"rss.packages\", \"/rss/packages.xml\", domain=warehouse)\n\n    # Legacy URLs\n    config.add_route(\"legacy.api.simple.index\", \"/simple/\", domain=warehouse)\n    config.add_route(\n        \"legacy.api.simple.detail\",\n        \"/simple/{name}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/\",\n        read_only=True,\n        domain=warehouse,\n    )\n    config.add_route(\n        \"legacy.api.json.project\",\n        \"/pypi/{name}/json\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}\",\n        read_only=True,\n        domain=warehouse,\n    )\n    config.add_route(\n        \"legacy.api.json.release\",\n        \"/pypi/{name}/{version}/json\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/{version}\",\n        read_only=True,\n        domain=warehouse,\n    )\n\n    # Legacy Action URLs\n    # TODO: We should probably add Warehouse routes for these that just error\n    #       and direct people to use upload.pypi.io\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.file_upload\",\n        \"file_upload\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.submit\",\n        \"submit\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.submit_pkg_info\",\n        \"submit_pkg_info\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.doc_upload\",\n        \"doc_upload\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.doap\",\n        \"doap\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.list_classifiers\",\n        \"list_classifiers\",\n        domain=warehouse,\n    )\n\n    # Legacy XMLRPC\n    config.add_xmlrpc_endpoint(\n        \"pypi\",\n        pattern=\"/pypi\",\n        header=\"Content-Type:text/xml\",\n        domain=warehouse,\n    )\n\n    # Legacy Documentation\n    config.add_route(\"legacy.docs\", config.registry.settings[\"docs.url\"])\n\n    # Legacy Redirects\n    config.add_redirect(\"/pypi/{name}/\", \"/project/{name}/\", domain=warehouse)\n    config.add_redirect(\n        \"/pypi/{name}/{version}/\",\n        \"/project/{name}/{version}/\",\n        domain=warehouse,\n    )\n    config.add_redirect(\"/packages/{path:.*}\", files_url, domain=warehouse)\n\n    # Legacy Action Redirects\n    config.add_pypi_action_redirect(\n        \"rss\",\n        \"/rss/updates.xml\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_redirect(\n        \"packages_rss\",\n        \"/rss/packages.xml\",\n        domain=warehouse,\n    )\n", "path": "warehouse/routes.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\ndef includeme(config):\n    # We need to get the value of the Warehouse and Forklift domains, we'll use\n    # these to segregate the Warehouse routes from the Forklift routes until\n    # Forklift is properly split out into it's own project.\n    warehouse = config.get_settings().get(\"warehouse.domain\")\n    files_url = config.get_settings()[\"files.url\"]\n\n    # Simple Route for health checks.\n    config.add_route(\"health\", \"/_health/\")\n\n    # Internal route to make it easier to force a particular status for\n    # debugging HTTPException templates.\n    config.add_route(\"force-status\", \"/_force-status/{status:[45]\\d\\d}/\")\n\n    # Basic global routes\n    config.add_route(\"index\", \"/\", domain=warehouse)\n    config.add_route(\"robots.txt\", \"/robots.txt\", domain=warehouse)\n    config.add_route(\"opensearch.xml\", \"/opensearch.xml\", domain=warehouse)\n    config.add_route(\"index.sitemap.xml\", \"/sitemap.xml\", domain=warehouse)\n    config.add_route(\n        \"bucket.sitemap.xml\",\n        \"/{bucket}.sitemap.xml\",\n        domain=warehouse,\n    )\n\n    # Some static, template driven pages\n    config.add_template_view(\"help\", \"/help/\", \"pages/help.html\")\n    config.add_template_view(\"security\", \"/security/\", \"pages/security.html\")\n    config.add_template_view(\n        \"sponsors\",\n        \"/sponsors/\",\n        # Use the full resource path here to make it able to be overridden by\n        # pypi-theme.\n        \"warehouse:templates/pages/sponsors.html\",\n    )\n\n    # Our legal policies\n    config.add_policy(\"terms-of-use\", \"terms.md\")\n\n    # HTML Snippets for including into other pages.\n    config.add_route(\n        \"includes.current-user-indicator\",\n        \"/_includes/current-user-indicator/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.flash-messages\",\n        \"/_includes/flash-messages/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.current-user-profile-callout\",\n        \"/_includes/current-user-profile-callout/{username}\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.edit-project-button\",\n        \"/_includes/edit-project-button/{project_name}\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"includes.edit-profile-button\",\n        \"/_includes/edit-profile-button/{username}\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n\n    # Search Routes\n    config.add_route(\"search\", \"/search/\", domain=warehouse)\n\n    # Accounts\n    config.add_route(\n        \"accounts.profile\",\n        \"/user/{username}/\",\n        factory=\"warehouse.accounts.models:UserFactory\",\n        traverse=\"/{username}\",\n        domain=warehouse,\n    )\n    config.add_route(\"accounts.login\", \"/account/login/\", domain=warehouse)\n    config.add_route(\"accounts.logout\", \"/account/logout/\", domain=warehouse)\n    config.add_route(\n        \"accounts.register\",\n        \"/account/register/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.request-password-reset\",\n        \"/account/request-password-reset/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.reset-password\",\n        \"/account/reset-password/\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"accounts.verify-email\",\n        \"/account/verify-email/\",\n        domain=warehouse,\n    )\n\n    # Management (views for logged-in users)\n    config.add_route(\"manage.account\", \"/manage/account/\", domain=warehouse)\n    config.add_route(\"manage.projects\", \"/manage/projects/\", domain=warehouse)\n    config.add_route(\n        \"manage.project.settings\",\n        \"/manage/project/{project_name}/settings/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.delete_project\",\n        \"/manage/project/{project_name}/delete_project/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.releases\",\n        \"/manage/project/{project_name}/releases/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.release\",\n        \"/manage/project/{project_name}/release/{version}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}/{version}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.roles\",\n        \"/manage/project/{project_name}/collaboration/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.change_role\",\n        \"/manage/project/{project_name}/collaboration/change/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.delete_role\",\n        \"/manage/project/{project_name}/collaboration/delete/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"manage.project.history\",\n        \"/manage/project/{project_name}/history/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{project_name}\",\n        domain=warehouse,\n    )\n\n    # Packaging\n    config.add_redirect('/p/{name}/', '/project/{name}/', domain=warehouse)\n    config.add_route(\n        \"packaging.project\",\n        \"/project/{name}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}\",\n        domain=warehouse,\n    )\n    config.add_route(\n        \"packaging.release\",\n        \"/project/{name}/{version}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/{version}\",\n        domain=warehouse,\n    )\n    config.add_route(\"packaging.file\", files_url)\n\n    # RSS\n    config.add_route(\"rss.updates\", \"/rss/updates.xml\", domain=warehouse)\n    config.add_route(\"rss.packages\", \"/rss/packages.xml\", domain=warehouse)\n\n    # Legacy URLs\n    config.add_route(\"legacy.api.simple.index\", \"/simple/\", domain=warehouse)\n    config.add_route(\n        \"legacy.api.simple.detail\",\n        \"/simple/{name}/\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/\",\n        read_only=True,\n        domain=warehouse,\n    )\n    config.add_route(\n        \"legacy.api.json.project\",\n        \"/pypi/{name}/json\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}\",\n        read_only=True,\n        domain=warehouse,\n    )\n    config.add_route(\n        \"legacy.api.json.release\",\n        \"/pypi/{name}/{version}/json\",\n        factory=\"warehouse.packaging.models:ProjectFactory\",\n        traverse=\"/{name}/{version}\",\n        read_only=True,\n        domain=warehouse,\n    )\n\n    # Legacy Action URLs\n    # TODO: We should probably add Warehouse routes for these that just error\n    #       and direct people to use upload.pypi.io\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.file_upload\",\n        \"file_upload\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.submit\",\n        \"submit\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.submit_pkg_info\",\n        \"submit_pkg_info\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.doc_upload\",\n        \"doc_upload\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.doap\",\n        \"doap\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_route(\n        \"legacy.api.pypi.list_classifiers\",\n        \"list_classifiers\",\n        domain=warehouse,\n    )\n\n    # Legacy XMLRPC\n    config.add_xmlrpc_endpoint(\n        \"pypi\",\n        pattern=\"/pypi\",\n        header=\"Content-Type:text/xml\",\n        domain=warehouse,\n    )\n\n    # Legacy Documentation\n    config.add_route(\"legacy.docs\", config.registry.settings[\"docs.url\"])\n\n    # Legacy Redirects\n    config.add_redirect(\"/pypi/{name}/\", \"/project/{name}/\", domain=warehouse)\n    config.add_redirect(\n        \"/pypi/{name}/{version}/\",\n        \"/project/{name}/{version}/\",\n        domain=warehouse,\n    )\n    config.add_redirect(\"/packages/{path:.*}\", files_url, domain=warehouse)\n\n    # Legacy Action Redirects\n    config.add_pypi_action_redirect(\n        \"rss\",\n        \"/rss/updates.xml\",\n        domain=warehouse,\n    )\n    config.add_pypi_action_redirect(\n        \"packages_rss\",\n        \"/rss/packages.xml\",\n        domain=warehouse,\n    )\n", "path": "warehouse/routes.py"}]}