3.2 统一资源标识(Uniform Resource Identifiers)
URI有许多名字,如WWW地址、通用文件标识(Universal Document Identifiers)、通用资源标识(Universal Resource Identifiers [2]),以及最终的统一资源定位符(Uniform Resource Locators (URL) [4])和统一资源名(URN)。在涉及HTTP以前,URI用简单格式的字符串描述-名字、位置、或其它特性,如网络资源。
3.2.1 一般语法(General Syntax)
在HTTP中URI可以用绝对形式表示,也可用相对于某一基本URI[9]的形式表示,具体取决于它们的使用方式。这两种形式的不同在于绝对URI总是以方法名称后跟“:”开头。
URI = ( absoluteURI | relativeURI ) [ "#" fragment ]
absoluteURI = scheme ":" *( uchar | reserved )
relativeURI = net_path | abs_path | rel_path
net_path = "//" net_loc [ abs_path ]
abs_path = "/" rel_path
rel_path = [ path ] [ ";" params ] [ "?" query ]
path = fsegment *( "/" segment )
fsegment = 1*pchar
segment = *pchar
params = param *( ";" param )
param = *( pchar | "/" )
scheme = 1*( ALPHA | DIGIT | "+" | "-" | "." )
net_loc = *( pchar | ";" | "?" )
query = *( uchar | reserved )
fragment = *( uchar | reserved )
pchar = uchar | ":" | "@" | "&" | "=" | "+"
uchar = unreserved | escape
unreserved = ALPHA | DIGIT | safe | extra | national
escape = "%" HEX HEX
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+"
extra = "!" | "*" | "'" | "(" | ")" | ","
safe = "$" | "-" | "_" | "."
unsafe = CTL | SP | <"> | "#" | "%" | "<" | ">"
national = <any OCTET excluding ALPHA, DIGIT,
Berners-Lee, et al Informational [Page 14]
reserved, extra, safe, and unsafe>
权威的URL语法及语义信息请参见RFC1738[4]和RFC1808[9]。上面所提到的BNF中包括了合法URL中不允许出现的符号(RFC1738),因为HTTP服务器并没有限制为只能用非保留字符集中的字符来表示地址路径,而且HTTP代理也可能接收到RFC1738没有定义的URI请求。
3.2.2 http URL
“http”表示要通过HTTP协议来定位网络资源。本节定义了HTTP URL的语法和语义。
http_URL = "http:" "//" host [ ":" port ] [ abs_path ]
host = <合法的Internet主机域名或IP地址(用十进制数及点组成)
,见RFC1123,2.1节定义>
port = *DIGIT
如是端口为空或没指定,则缺省为80端口。对于绝对路径的URI来说,拥有被请求的资源的服务器主机通过侦听该端口的TCP连接来接收该URI请求。如果URL中没有给出绝对路径,要作为请求URI(参见5.1.2节)使用,必须以“/”形式给出。
注意:虽然HTTP协议独立于传输层协议,http URL只是标识资源的TCP位置,而对于非TCP资源来说,必须用其它的URI形式来标识。
规范的HTTP URL形式可通过将主机中的大写字符转换成小写(主机名是大小写敏感的)来获得。如果端口是80,去掉冒号及端口号,并将空路径替换成“/”。
3.3 Date/Time 格式(Date/Time Formats)
出于历史原因,HTTP/1.0应用允许三种格式来表示时间戳:
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
Berners-Lee, et al Informational [Page 15]
第一种格式是首选的Internet标准格式,表示方法长度固定(RFC1123[6])。第二种格式在普通情况下使用,但是它是基于已经废弃的RFC850[10]中的日期格式,而且年不是用四位数字表示的。HTTP/1.0 客户端及服务器端在解析日期时可识别全部三种格式,但是它们不可以产生第三种时间格式(asctime) 。
注意:对于接收到由非HTTP应用产生的日期数据时,提倡对接收到的日期值进行填充。这样做是因为,在某些时候,代理或网关可能通过SMTP或NNTP来获取或发送消息。
所有的HTTP/1.0 date/timp时间戳必须用世界时间(Universal Time,UT),即格林威治时间来表示(Greenwich Mean Time,GMT),没有任何修改的余地。前面的两种格式用了“GMT”表示时区,在读ASC表示的时间时,也应假定是这个时区。
HTTP-date = rfc1123-date | rfc850-date | asctime-date
rfc1123-date = wkday "," SP date1 SP time SP "GMT"
rfc850-date = weekday "," SP date2 SP time SP "GMT"
asctime-date = wkday SP date3 SP time SP 4DIGIT
date1 = 2DIGIT SP month SP 4DIGIT
; day month year (e.g., 02 Jun 1982)
date2 = 2DIGIT "-" month "-" 2DIGIT
; day-month-year (e.g., 02-Jun-82)
date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
; month day (e.g., Jun 2)
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; 00:00:00 - 23:59:59
wkday = "Mon" | "Tue" | "Wed"
| "Thu" | "Fri" | "Sat" | "Sun"
weekday = "Monday" | "Tuesday" | "Wednesday"
| "Thursday" | "Friday" | "Saturday" | "Sunday"
month = "Jan" | "Feb" | "Mar" | "Apr"
| "May" | "Jun" | "Jul" | "Aug"
| "Sep" | "Oct" | "Nov" | "Dec"
注意:HTTP要求只能在协议流中使用data/time时间戳格式,不要求客户端及服务器端在用户描述、请求登录等情况下使用这类格式。
Berners-Lee, et al Informational [Page 16]
3.4 字符集(Character Sets)
HTTP所使用的字符集定义和描述MIME时用的相同:
本文档用字符集(character set)来指明利用一个或多个表将顺序字节转换成顺序字符的方法。注意,不需要其它方向的无条件转换,因为不是所有的字符都可以用给定字符集来表示,同时,一个字符集也可能提供一种以上的字节顺序来表示一种特殊的字符。这种定义倾向于允许不同类型的字符编码通过简单的单表映射来实现,如,从表US-ASCII切换到复杂表如ISO2202。实际上,与MIME字符集名相关的定义必须完整指定从字节到字符的映射,特别是不允许通过利用外部配置信息来确定精确的映射。
注意:术语字符集(character set)归于字符编码(character encoding)。事实上,由于HTTP与MIME共同使用同样的注册,所以其术语也应一致。
HTTP字符集由大小写敏感的符号组成。全部的符号定义参见IANA字符集注册[15]。因为注册处不会为每个字符集单独定义一套符号,所以我们在这看到的字符集名大多是与HTTP实体使用相关的。这些在RFC 1521 [5] 中注册的字符集,即US-ASCII [17] 及ISO-8859 [18]字符集,还有一些其它字符集被强烈建议在MIME字符集参数内部使用。
charset = "US-ASCII"
| "ISO-8859-1" | "ISO-8859-2" | "ISO-8859-3"
| "ISO-8859-4" | "ISO-8859-5" | "ISO-8859-6"
| "ISO-8859-7" | "ISO-8859-8" | "ISO-8859-9"
| "ISO-2022-JP" | "ISO-2022-JP-2" | "ISO-2022-KR"
| "UNICODE-1-1" | "UNICODE-1-1-UTF-7" | "UNICODE-1-1-UTF-8"
| token
虽然HTTP允许使用专用符号做为字符集值,但是任何在IANA字符集注册表[15]中有预定义值的符号都必须表明其所属的字符集。应用应当将其对字符集的使用限制在IANA注册表规定的范围之内。
Berners-Lee, et al Informational [Page 17]
实体主体的字符集如果属于US-ASCII 或ISO-8859-1字符集,则勿需标记,否则,应当用主体字符编码方式中的最基本命名来标记。
3.5 内容译码(Content Codings)
内容译码值用于指示对资源进行的编码转换。内容译码主要用于将经过压缩、加密等操作的文件进行还原,使其保持其原来的介质类型。典型情况下,经过编码保存的资源只能经过解码或类似的操作才能还原。
content-coding = "x-gzip" | "x-compress" | token
注意:出于对未来兼容性的考虑,HTTP/1.0应用应将"gzip" 和"compress" 分别与 "x-gzip"和"x-compress"对应起来。
所有的内容译码值都是大小写敏感的。HTTP/1.0在内容编码(10.3节)头域中使用内容译码值。虽然该值描述的是内容译码,但更为重要的是,它指明了应当用什么机制来进行解码。注意,单独的程序可能有能力实现对多种格式编码的解码。
在这段文字中,提到了两个值:
x-gzip
文件压缩程序"gzip" (GNU zip,由Jean-loup Gailly开发)的编码格式。该格式属于典型的带有32位CRC 校验的Lempel-Ziv译码 (LZ77)。
x-compress
文件压缩程序"compress"的编码格式,该格式适用于LZW(Lempel-Ziv-Welch)译码。
注意:用程序名来标识编码格式的做法不是很理想,在将来可能不会继续这样做。现在之所以这样做是出于历史的原因,并非良好的设计。
Berners-Lee, et al Informational [Page 18]
3.6 介质类型(Media Types)
HTTP在Content-Type header域(10.5节)中使用Internet介质类型[13],用以提供开放的可扩展的数据类型。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
参数可参照属性/值对的方式,用类型/子类型的格式来写。
Parameter = attribute "=" value
Attribute = token
Value = token | quoted-string
其中,类型、子类型、参数属性名是大小写敏感的。而参数值不一定是大小写敏感的,这得看参数名的语法而定。在类型和子类型、属性名和属性值之间不能有LWS(空格)。当接收到不能识别的介质类型的参数时,用户代理应当忽略它们。
一些老的HTTP应用不能识别介质类型参数,所以HTTP/1.0的应用程序只能在定义消息内容时使用介质参数。
介质参数(Media-type)值用Internet授权分配数字(Internet Assigned Number Authority ,IANA [15])注册。介质类型注册过程请参见RFC1590[13]。不鼓励使用未注册的介质类型。
3.6.1标准及文本缺省(Canonicalization and Text Defaults)
Internet介质类型是用规范形式注册的。一般来说,在通过HTTP协议传输实体主体(Entity-Body)之前,必须先将其表示成适当的规范格式。如果主体用使用了一种Content-Encoding进行编码,下面的数据在编码前必须转换成规范形式:
“text”类型的介质子类型在规范形式中使用CRLF做为文本行中断。实际上,为和实体主体(Entity body)内的使用方式保持一致,HTTP允许传输纯以CR或LF单独表示行中断的文本介质。HTTP应用程序必须将其通过HTTP方式接收到的文本介质中的CRLF、CR、LF看做是行中断符。
Berners-Lee, et al Informational [Page 19]
另外,如果文本介质的字符集没有使用字节13和10做为CR和LF,象一些多字节字符集,HTTP允许使用该字符集指定的任何顺序的字节替代CR和LF做为行中断,这种行中断的灵活运用方式仅可于实体主体(Entity-Body)中。一个纯CR或LF不应在任何HTTP控制结构(如标题域-header field和多块分界线-multipart boundaries)中替代CRLF。
参数"charset"在定义数据的字符集(3.4节)时,与一些介质类型一起使用。当发送方没有显式给出字符参数时,HTTP在接收时将”text”的介质子类型定义为缺省值”ISO-8859-1”。”ISO-8859-1”字符集或其子集以外的数据必须要标记其相应的字符集值,这样可以保证接收方能正确地对其进行解析。
注意:许多当前HTTP服务器提供的数据使用”ISO-8859-1”以外的其它字符集,而且也没有正确的进行标记,这种工作方式限制了互操作性,建议不要采用。做为一种补救方法,一些HTTP用户代理提供了配置选项,使用户可以在字符集参数没指定的情况下,自行更改缺省的介质类型解释方式。
3.6.2 多部分类型(Multipart Types)
MIME提供了多部分("multipart")类型的数字――在一个单独的消息实体主体(Entity-Body)内可以封装几个实体(entities)。虽然用户代理可能需要了解每种类型,从而可以正确解释每部分主体的意图,但是在IANA[15]的多部分类型(multipart types)注册中却找不到专为HTTP/1.0所指定的内容。HTTP用户代理只得自己来做接收多部分类型的工作,其过程和行为与MIME用户代理是相同或相似的。HTTP服务器不应假定HTTP客户端都有能力处理多部分类型。
所有的多部分类型都使用通用的语法,而且必须在介质类型值部分包括边界参数(boundary parameter)。消息的主体是其自身,做为协议元素,它必须只使用CRLF做为段间(body-parts)的行中断符。多段主体(Multipart body-parts)中可能包括对各段有重要意义的HTTP标题域。
3.7 产品标识(Product Tokens)
是通讯应用程序用来标识其自身的一个简单符号,常和任意字母及版本描述一起使用。大多数产品标识也将其产品的重要组成部分的版本号一起列出,中间用空格分隔。
Berners-Lee, et al Informational [Page 20]