Repository: ietf-tools/datatracker

Issue:
doc url parser accepts revision for rfcs
/doc/rfc8989/99/ works by unintended consequence (redirecting to /doc/rfc8989.
/doc/rfc8989/99/bibtex works (producing bibtex for rfc8989.

Both should 404 instead.



Discussion:
For info: `/idnits2-state` too, I suppose.

Resolving patch:
diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py
--- a/ietf/doc/views_doc.py
+++ b/ietf/doc/views_doc.py
@@ -191,6 +191,9 @@ def interesting_doc_relations(doc):
     return interesting_relations_that, interesting_relations_that_doc
 
 def document_main(request, name, rev=None, document_html=False):
+    if name.startswith("rfc") and rev is not None:
+        raise Http404()
+
     doc = get_object_or_404(Document.objects.select_related(), docalias__name=name)
 
     # take care of possible redirections
@@ -1080,6 +1083,9 @@ def document_history(request, name):
 
 
 def document_bibtex(request, name, rev=None):
+    if name.startswith('rfc') and rev is not None:
+        raise Http404()
+
     # Make sure URL_REGEXPS did not grab too much for the rev number
     if rev != None and len(rev) != 2:
         mo = re.search(r"^(?P<m>[0-9]{1,2})-(?P<n>[0-9]{2})$", rev)
diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py
--- a/ietf/doc/views_search.py
+++ b/ietf/doc/views_search.py
@@ -290,8 +290,8 @@ def cached_redirect(cache_key, url):
             redirect_to = find_unique(rev_split.group(1))
             if redirect_to:
                 rev = rev_split.group(2)
-                # check if we can redirect directly to the rev
-                if DocHistory.objects.filter(doc__docalias__name=redirect_to, rev=rev).exists():
+                # check if we can redirect directly to the rev if it's draft, if rfc - always redirect to main page
+                if not redirect_to.startswith('rfc') and DocHistory.objects.filter(doc__docalias__name=redirect_to, rev=rev).exists():
                     return cached_redirect(cache_key, urlreverse("ietf.doc.views_doc.document_main", kwargs={ "name": redirect_to, "rev": rev }))
                 else:
                     return cached_redirect(cache_key, urlreverse("ietf.doc.views_doc.document_main", kwargs={ "name": redirect_to }))


Test patch:
diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py
--- a/ietf/doc/tests.py
+++ b/ietf/doc/tests.py
@@ -261,6 +261,17 @@ def test_search_for_name(self):
         parsed = urlparse(r["Location"])
         self.assertEqual(parsed.path, urlreverse('ietf.doc.views_search.search'))
         self.assertEqual(parse_qs(parsed.query)["name"][0], "draft-ietf-doesnotexist-42")
+    
+    def test_search_rfc(self):
+        rfc = WgRfcFactory(name="rfc0000")
+        
+        # search for existing RFC should redirect directly to the RFC page
+        r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=rfc.name)))
+        self.assertRedirects(r, f'/doc/{rfc.name}/', status_code=302, target_status_code=200)
+
+        # search for existing RFC with revision number should redirect to the RFC page
+        r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=rfc.name + "-99")), follow=True)
+        self.assertRedirects(r, f'/doc/{rfc.name}/', status_code=302, target_status_code=200)
 
     def test_frontpage(self):
         r = self.client.get("/")
@@ -1617,6 +1628,10 @@ def test_document_charter(self):
         CharterFactory(name='charter-ietf-mars')
         r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name="charter-ietf-mars")))
         self.assertEqual(r.status_code, 200)
+    
+    def test_incorrect_rfc_url(self):
+        r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name="rfc8989", rev="00")))
+        self.assertEqual(r.status_code, 404)
 
     def test_document_conflict_review(self):
         ConflictReviewFactory(name='conflict-review-imaginary-irtf-submission')
@@ -1993,6 +2008,12 @@ def test_document_bibtex(self):
         #
         self.assertNotIn('day', entry)
 
+        # test for incorrect case - revision for RFC
+        rfc = WgRfcFactory(name="rfc0000")
+        url = urlreverse('ietf.doc.views_doc.document_bibtex', kwargs=dict(name=rfc.name, rev='00'))
+        r = self.client.get(url)
+        self.assertEqual(r.status_code, 404)
+
         april1 = IndividualRfcFactory.create(
                   stream_id =       'ise',
                   states =          [('draft','rfc'),('draft-iesg','pub')],