Network Working Group R. Moats Request for Comments: 2648 AT&T Category: Informational August 1999
A URN Namespace for IETF Documents
Status of this Memo
This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1999). All Rights Reserved.
Abstract
A system for Uniform Resource Names (URNs) must be capable of supporting new naming systems. As an example of proposing a new namespace, this document proposes the "ietf" namespace. This namespace consists of the RFC family of documents (RFCs, STDs, FYIs, and BCPs) developed by the IETF and published by the RFC Editor, the minutes of working groups (WG) and birds of a feather (BOF) meetings that occur during IETF conferences, and the Internet Drafts published by the Internet Drafts Editor. Both the current URN framework and URN syntax support this namespace.
This document proposes the "ietf" namespace, which consists of the RFC family of documents (RFCs, STDs, FYIs, and BCPs) developed by the IETF and published by the RFC editor and the minutes of working groups (WG) and birds of a feather (BOF) meetings that occur during IETF conferences.
The namespace specification is for a formal namespace.
rfc-nss = "rfc:" 1*DIGIT fyi-nss = "fyi:" 1*DIGIT std-nss = "std:" 1*DIGIT bcp-nss = "bcp:" 1*DIGIT draft-nss = "id:" string mtg-nss = "mtg:" string other-nss = string ; beginning with a prefix other than one of those ; above for future expansion
string = 1*(DIGIT / ALPHA / "-")
If the IESG (or it successor) adds a new document series, this ABNF specification will need to be updated. Further, if a working group or BOF is created that used characters outside the range of this ABNF specification, this specification will need to be updated. Any system intended to resolve names for this namespace should be written with the awareness that this could occur at any time.
RFC 2648 A URN Namespace for IETF Documents August 1999
Identifier uniqueness considerations:
Because the rfc-editor assigns the RFC number uniquely these URNs are unique. Since the mapping between RFCs and other rfc-editor document series (STDs, FYIs or BCPs) is not necessarily one-to-one, uniqueness of STDs, FYIs and BCPs are defined based on the document mappings maintained by the RFC Editor (the index files "rfc-index.txt", "fyi- index.txt", "bcp-index.txt", "std-index.txt") are defined to be the definitive statement of the assignment of RFC Family URNs in this namespace. The meeting minutes portion of the namespace is guaranteed unique because the URN includes the sequence number of the IETF conference. The document mapping maintained by the Internet Drafts editor ("1id- abstracts.txt") is defined as the definitive statement of the assignment of URNs for the internet draft portion of this namespace.
Identifier persistence considerations:
Persistence of the URNs of this namespace is independent of the mutability of the underlying documents. A URN once assigned will never be reassigned to a different resource; the assignment is persistent and immutable. Immutability of RFCs, STDs, FYIs and BCPs is at the discretion of the RFC Editor. They may be composites of one or more RFCs and the set of RFCs that includes them may change with time. It is important to note that this mutability of some resources is independent of the immutability of URN assignment to a resource.
Process of identifier assignment:
Assignment of URNs from this namespace occurs in three ways. The first is through publication of a new RFC, FYI, STD or BCP is by the RFC Editor. This new document will have a new series number and will therefore define a new URN. The document mappings maintained by the RFC Editor (the index files "rfc-index.txt", "fyi-index.txt", "bcp-index.txt" and "std-index.txt") are defined to be the definitive statement of the assignment of RFC Family URNs in this namespace.
The second way a URN is assigned is through the filing of meeting minutes by a working group or birds of a feather as part of an IETF conference. The list of minutes maintained by the IETF for each working group and conference in the subtree pointed at by the URL ftp://ietf.org/ietf/ is considered the definitive assignment of URNs for working
Moats Informational [Page 3]
RFC 2648 A URN Namespace for IETF Documents August 1999
group or birds of a feather minutes.
The third way a URN is assigned is through the publication of a new internet-draft by the Internet Draft Editor. This draft will have a distinct name (and version number) and therefore defined a new URN. The document mapping maintained by the Internet Drafts editor ("1id- abstracts.txt") is defined as the definitive statement of the assignment of URNs for this portion of the namespace.
Process of identifier resolution:
A mirrored copy of the underlying documentation is required to resolve these URNs. Resolution via HTTP is done by a set of simple Perl cgi-bin scripts presented in Appendix A.
Because this namespace defines no additional reserved characters, it does not add any security considerations beyond those inherent from the existence of the reserved characters from [1]. Further, none of the reserved characters from [1] are used in the definition of the NSS. This means that resolvers for this namespace may be considered "secure" in the sense that any escaping of characters in the NSS MUST result in the resolver indicating that the URN has incorrect syntax.
Thanks to various members of the URN working group for comments on earlier drafts of this document. The work described in this document is partially supported by the National Science Foundation, Cooperative Agreement NCR-9218179.
my($wgpath) = "/ftp/ietf"; my($urn) = $ENV{'QUERY_STRING'}; my($host) = $ENV{'SERVER_NAME'}; #get my host name for ftp: URLs my($accept) = $ENV{'HTTP_ACCEPT'}; #this is the "Accept:" HTTP header
(&resolveid($1), exit) if ($urn =~ /urn:ietf:id:(\S+)/i); (&resolverfc($1, $2), exit) if ($urn =~ /urn:ietf:(\w*):(\d*)/i); (&resolvemtg($1, $2), exit) if ($urn =~ /urn:ietf:mtg:(\d*)-(\w*)/i); &urn_error("400 Bad Request\n");
sub resolvemtg { my($ietfnum, $sesnam) = @_; &urn_error("404 Not Found\n") if (!defined $number2date{$ietfnum}); my($date)=$number2date{$ietfnum};
Moats Informational [Page 6]
RFC 2648 A URN Namespace for IETF Documents August 1999
my($link)="$wgpath/$sesnam/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 200 OK\r\n"; print "Content-type: text/html\r\n\r\n"; print "<HTML>\n<TITLE>Citation for $urn</TITLE>\n"; print "<BODY>\n"; print "<H1><A HREF=\"$link\">$urn</A>:</H1>\n"; print "Minutes of the $sesnam working group from the " . &end($ietfnum) . " IETF"; print "</BODY>\n</HTML>\n"; return; } my($link)="$wgpath/$date/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 200 OK\r\n"; print "Content-type: text/html\r\n\r\n"; print "<HTML>\n<TITLE>Citation for $urn</TITLE>\n"; print "<BODY>\n"; print "<H1><A HREF=\"$link\">$urn</A>:</H1>\n"; print "Minutes of the $sesnam working group from the " . &end($ietfnum) . " IETF"; print "</BODY>\n</HTML>\n"; return; } &urn_error("404 Not Found\n"); }
sub end { my($inarg)=@_; return $inarg . "st" if ($inarg =~ /1$/); return $inarg . "nd" if ($inarg =~ /2$/); return $inarg . "rd" if ($inarg =~ /3$/); return $inarg . "th"; }
sub resolverfc { my($flag,@bib,$i,$k,$j,$done,@ref); my($l,$link); my($scheme, $value) = @_; $scheme =~ tr/A-Z/a-z/; if (!defined $cite{$scheme}) { &urn_error("404 Not Found\n"); }
$flag = 0; open(INPUT, "$cite{$scheme}"); while (<INPUT>) { $flag = 1 if (/^0*$value /);
Moats Informational [Page 7]
RFC 2648 A URN Namespace for IETF Documents August 1999
if ($flag == 1) { last if (/^$/); chop; push @bib,$_; } }
if ($scheme ne "rfc") { print "Status: 200 OK\r\n"; print "Content-type: text/html\r\n\r\n"; $bib[0] =~ s/^[0-9]*\s*/<B>/; for ($i=0; $i<=$#bib; $i+=1) { last if ($bib[$i] =~ s/\./.<\/B>/); } for ($i=0;$i<=$#bib;$i+=1) { $k=$bib[$i]; while ($k =~ /(fyi|std|rfc|bcp)([0-9]+)(.*)/i) { push @ref,"$1$2"; $k=$3; } $done=""; foreach $j (@ref) { next if ($done =~ $j); $done .= "$j "; $l = $j; $l =~ tr/A-Z/a-z/; $link=&make_link("$l"); $bib[$i] =~ s/$j/<A HREF="$link">$j<\/A>/g; } } print "<HTML>\n<TITLE>Citation for $urn</TITLE>\n"; print "<BODY>\n"; $link=&make_link("$scheme$value"); print "<H1><A HREF=\"$link\">$scheme$value</A>:</H1>\n"; foreach $i (@bib) { print "$i\n"; } print "</BODY>\n</HTML>\n"; } else { print "Status: 200 OK\r\n"; print "Content-type: text/html\r\n\r\n"; $bib[0] =~ s/^[0-9]*\s*//; $j=0; for ($i=0; $i<=$#bib; $i+=1) { $j += ($bib[$i] =~ s/, "/, <B>"/); $j += ($bib[$i] =~ s/",/"<\/B>,/); } for ($i=0;$i<=$#bib;$i+=1) {
Moats Informational [Page 8]
RFC 2648 A URN Namespace for IETF Documents August 1999
my($wgpath) = "/ftp/ietf"; my($urn) = $ENV{'QUERY_STRING'}; my($host) = $ENV{'SERVER_NAME'}; #get my host name for ftp: URLs my($accept) = $ENV{'HTTP_ACCEPT'}; #this is the "Accept:" HTTP header
(&resolveid($1), exit) if ($urn =~ /urn:ietf:id:(\S+)/i); (&resolverfc($1, $2), exit) if ($urn =~ /urn:ietf:(\w*):(\d*)/i); (&resolvemtg($1, $2), exit) if ($urn =~ /urn:ietf:mtg:(\d*)-(\w*)/i); &urn_error("400 Bad Request\n");
sub resolvemtg { my($ietfnum, $sesnam) = @_; &urn_error("404 Not Found\n") if (!defined $number2date{$ietfnum}); my($date)=$number2date{$ietfnum}; my($link)="$wgpath/$sesnam/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 302 Moved temporarily\n"; print "Location: $link\n";
Moats Informational [Page 11]
RFC 2648 A URN Namespace for IETF Documents August 1999
return; } my($link)="$wgpath/$date/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 302 Moved temporarily\n"; print "Location: $link\n"; return; } &urn_error("404 Not Found\n"); }
sub end { my($inarg)=@_; return $inarg . "st" if ($inarg =~ /1$/); return $inarg . "nd" if ($inarg =~ /2$/); return $inarg . "rd" if ($inarg =~ /3$/); return $inarg . "th"; }
sub resolverfc { my($flag,@bib,$i,$k,$j,$done,@ref); my($l,$link); my($scheme, $value) = @_; $scheme =~ tr/A-Z/a-z/; &urn_error("404 Not Found\n")if (!defined $pathbase{$scheme}); my($txttry)="/ftp/$pathbase{$scheme}$value.txt"; my($pstry)="/ftp/$pathbase{$scheme}$value.ps"; my($htmltry)="/ftp/$pathbase{$scheme}$value.html"; MIME_SWITCH: { if ($accept =~ /application\/postscript/ && -f $pstry) { print "Status: 302 Moved temporarily\n"; print "Location: http://$host/$pathbase{$scheme}$value.ps\n\n"; last MIME_SWITCH; } if ($accept =~ /text\/html/ && -f $htmltry) { print "Status: 302 Moved temporarily0; print "Location: http://$host/$pathbase{$scheme}$value.html\n\n"; last MIME_SWITCH; } if ($accept =~ /\*\/\*|text\/plain/ && -f $txttry) { print "Status: 302 Moved temporarily\n"; print "Location: http://$host/$pathbase{$scheme}$value.txt\n\n"; last MIME_SWITCH; } &urn_error("404 Not Found\n"); } }
Moats Informational [Page 12]
RFC 2648 A URN Namespace for IETF Documents August 1999
sub urn_error { my($code) = @_; #store failure code here...
print "Status: $code"; print "Content-type: text/html\n\n<HTML>\n"; print "<head><title>URN Resolution: I2L $code</title></head>\n"; print "<BODY>\n"; print "<h1>URN to URL resolution failed for the URN:</h1>\n"; print "<hr><h3>$urn</h3>\n"; print "</body>\n"; print "</html>\n"; exit; }
sub resolveid { my($flag,@bib,$i,$k,$j,$done,@ref); my($l,$link); my($scheme) = "id"; my($value) = @_; $scheme =~ tr/A-Z/a-z/; &urn_error("404 Not Found\n")if (!defined $pathbase{$scheme}); my($txttry)="/ftp/$pathbase{$scheme}$value.txt"; my($pstry)="/ftp/$pathbase{$scheme}$value.ps"; my($htmltry)="/ftp/$pathbase{$scheme}$value.html"; MIME_SWITCH: { if ($accept =~ /application\/postscript/ && -f $pstry) { print "Status: 302 Moved temporarily\n"; print "Location: http://$host/$pathbase{$scheme}$value.ps\n\n"; last MIME_SWITCH; } if ($accept =~ /text\/html/ && -f $htmltry) { print "Status: 302 Moved temporarily\n"; print "Location: http://$host/$pathbase{$scheme}$value.html\n\n"; last MIME_SWITCH; } if ($accept =~ /\*\/\*|text\/plain/ && -f $txttry) { print "Status: 302 Moved temporarily\n"; print "Location: http://$host/$pathbase{$scheme}$value.txt\n\n"; last MIME_SWITCH; } &urn_error("404 Not Found\n"); } }
Moats Informational [Page 13]
RFC 2648 A URN Namespace for IETF Documents August 1999
my($wgpath) = "/ftp/ietf"; my($urn) = $ENV{'QUERY_STRING'}; my($host) = $ENV{'SERVER_NAME'}; #get my host name for ftp: URLs my($accept) = $ENV{'HTTP_ACCEPT'}; #this is the "Accept:" HTTP header
(&resolveid($1), exit) if ($urn =~ /urn:ietf:id:(\S+)/i); (&resolve1($1, $2), exit) if ($urn =~ /urn:ietf:(\w*):(\d*)/i); (&resolve2($1, $2), exit) if ($urn =~ /urn:ietf:mtg:(\d*)-(\w*)/i); &urn_error("400 Bad Request\n");
sub resolve2 { my($ietfnum, $sesnam) = @_; &urn_error("404 Not Found\n") if (!defined $number2date{$ietfnum}); my($date)=$number2date{$ietfnum}; my($link)="$wgpath/$sesnam/$sesnam-minutes-$date.txt"; if (-f $link) {
Moats Informational [Page 14]
RFC 2648 A URN Namespace for IETF Documents August 1999
my($wgpath) = "/ftp/ietf"; my($urn) = $ENV{'QUERY_STRING'}; my($host) = $ENV{'SERVER_NAME'}; #get my host name for ftp: URLs my($accept) = $ENV{'HTTP_ACCEPT'}; #this is the "Accept:" HTTP header
print "$urn\n"; (&resolveid($1), exit) if ($urn =~ /urn:ietf:id:(\S+)/i); (&resolve1($1, $2), exit) if ($urn =~ /urn:ietf:(\w*):(\d*)/i); (&resolve2($1, $2), exit) if ($urn =~ /urn:ietf:mtg:(\d*)-(\w*)/i); &urn_error("400 Bad Request\n");
sub resolve2 { my($ietfnum, $sesnam) = @_; &urn_error("404 Not Found\n") if (!defined $number2date{$ietfnum}); my($date)=$number2date{$ietfnum}; my($link)="$wgpath/$sesnam/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 200 OK\n"; print "Content-type: text/plain\n\n"; open(FILE, "$link"); while (<FILE>) { print $_; } close FILE; return; } my($link)="$wgpath/$date/$sesnam-minutes-$date.txt"; if (-f $link) { print "Status: 200 OK\n"; print "Content-type: text/plain\n\n"; open(FILE, "$link"); while (<FILE>) { print $_; } close FILE; return; } &urn_error("404 Not Found\n"); }
Moats Informational [Page 23]
RFC 2648 A URN Namespace for IETF Documents August 1999
sub end { my($inarg)=@_; return $inarg . "st" if ($inarg =~ /1$/); return $inarg . "nd" if ($inarg =~ /2$/); return $inarg . "rd" if ($inarg =~ /3$/); return $inarg . "th"; }
sub resolve1 { my($flag,@bib,$i,$k,$j,$done,@ref); my($l,$link); my($scheme, $value) = @_; $scheme =~ tr/A-Z/a-z/; &urn_error("404 Not Found\n")if (!defined $pathbase{$scheme}); my($txttry)="/ftp/$pathbase{$scheme}$value.txt"; my($pstry)="/ftp/$pathbase{$scheme}$value.ps"; my($htmltry)="/ftp/$pathbase{$scheme}$value.html"; MIME_SWITCH: { if ($accept =~ /application\/postscript/ && -f $pstry) { print "Status: 200 OK\n"; print "Content-type: application/postscript\n\n"; open(FILE, "$pstry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; } if ($accept =~ /text\/html/ && -f $htmltry) { print "Status: 200 OK\n"; print "Content-type: text/html\n\n"; open(FILE, "$htmltry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; } if ($accept =~ /\*\/\*|text\/plain/ && -f $txttry) { print "Status: 200 OK\n"; print "Content-type: text/plain\n\n"; open(FILE, "$txttry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; }
Moats Informational [Page 24]
RFC 2648 A URN Namespace for IETF Documents August 1999
&urn_error("404 Not Found\n"); } }
sub resolveid { my($flag,@bib,$i,$k,$j,$done,@ref); my($l,$link); my($scheme) = "id"; my($value) = @_; $scheme =~ tr/A-Z/a-z/; &urn_error("404 Not Found\n")if (!defined $pathbase{$scheme}); my($txttry)="/ftp/$pathbase{$scheme}$value.txt"; my($pstry)="/ftp/$pathbase{$scheme}$value.ps"; my($htmltry)="/ftp/$pathbase{$scheme}$value.html"; MIME_SWITCH: { if ($accept =~ /application\/postscript/ && -f $pstry) { print "Status: 200 OK\n"; print "Content-type: application/postscript\n\n"; open(FILE, "$pstry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; } if ($accept =~ /text\/html/ && -f $htmltry) { print "Status: 200 OK\n"; print "Content-type: text/html\n\n"; open(FILE, "$htmltry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; } if ($accept =~ /\*\/\*|text\/plain/ && -f $txttry) { print "Status: 200 OK\n"; print "Content-type: text/plain\n\n"; open(FILE, "$txttry"); while (<FILE>) { print $_; } close FILE; last MIME_SWITCH; } &urn_error("404 Not Found\n"); } }
Moats Informational [Page 25]
RFC 2648 A URN Namespace for IETF Documents August 1999
sub urn_error { my($code) = @_; #store failure code here...
print "Status: $code"; print "Content-type: text/html\n\n<HTML>\n"; print "<head><title>URN Resolution: I2R $code</title></head>\n"; print "<BODY>\n"; print "<h1>URN to URL resolution failed for the URN:</h1>\n"; print "<hr><h3>$urn</h3>\n"; print "</body>\n"; print "</html>\n"; exit; }
RFC 2648 A URN Namespace for IETF Documents August 1999
my($host) = $ENV{'SERVER_NAME'}; #get my host name for ftp: URLs my($accept) = $ENV{'HTTP_ACCEPT'}; #this is the "Accept:" HTTP header
(&resolveid($1), exit) if ($urn =~ /urn:ietf:id:(\s*)/i); (&resolve1($1, $2), exit) if ($urn =~ /urn:ietf:(\w*):(\d*)/i); (&resolve2($1, $2), exit) if ($urn =~ /urn:ietf:mtg:(\d*)-(\w*)/i); &urn_error("400 Bad Request\n");
sub resolve2 { my($ietfnum, $sesnam) = @_; my(@vers,$i); &urn_error("404 Not Found\n") if (!defined $number2date{$ietfnum}); my($date)=$number2date{$ietfnum}; my($link)="$wgpath/$sesnam/$sesnam-minutes-$date.txt";
if (-f $link) { push(@vers,$link); } $link="$wgpath/$date/$sesnam-minutes-$date.txt"; if (-f $link) { push(@vers,$link); } &urn_error("404 Not Found\n") if ($#vers==-1);
} if ($i =~ /txt$/) { print "Content-Type: text/plain\n\n"; } if ($i =~ /ps$/) { print "Content-Type: application/postscript\n\n"; } open(FILE, "$i"); while (<FILE>) { print "$_"; } close FILE; } print "--endpart\n"; } sub urn_error { my($code) = @_; #store failure code here...
print "Status: $code"; print "Content-type: text/html\n\n<HTML>\n"; print "<head><title>URN Resolution: I2Rs $code</title></head>\n"; print "<BODY>\n"; print "<h1>URN to URL resolution failed for the URN:</h1>\n"; print "<hr><h3>$urn</h3>\n"; print "</body>\n"; print "</html>\n"; exit; }
Moats Informational [Page 29]
RFC 2648 A URN Namespace for IETF Documents August 1999
Full Copyright Statement
Copyright (C) The Internet Society (1999). All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement
Funding for the RFC Editor function is currently provided by the Internet Society.