基于ABNF描述的HTTP协议格式

定义一个协议的时候,会遇到这样的问题:协议的数据段之间分隔符是什么,字段之间可以用什么字符分隔,空白符可以连续多少个,所以需要一门元语言来准确描述这些规则。

例如,在一个HTTP请求中, HOST: 后面是否可以连续有多个空格?在计算机科学中,ABNF(augmented Backus–Naur form,巴科斯范式)是我们经常遇到的一种的规则定义语言,广泛存在于各种标准文档中。

ABNF规范

ABNF范式由一组派生规则组成:

rule = definition ; comment CRLF

  • rule
    大小写不敏感的非终结符

  • definition
    定义规则的一串符号

  • comment
    用于注释

  • CRLF
    回车换行,用于结束

最终值

最终值由一个或多个数值字符指定。

  • 数值字符的组成:

%base + value

  • base, 即基数:
%b 二进制
%d 十进制
%x 十六进制
  • “.”表示串联

例如:

%d13.10 表示回车换行

操作符

  • 空白符

空白字符被用来分隔定义中的各个元素.WSP 为单个空白符,LWSP 为包含换行符的零个或者多个空白字符

  • 注释;

; comment

注释以 ; 开始,到行尾结束。

  • 串联

Rule1 Rule2

规则由规则名的序列定义。

foo = %x61 ; a  
bar = %x62 ;  b  
number = foo bar foo

则number表示aba

  • 选择

Rule1 / Rule2

规则由被"/"分隔的规则序列定义。

fubar = fu / bar

选择 fu规则 或者 bar规则

  • 增量选择

Rule1 =/ Rule2

增量选择用于向一个规则增加补充选择。

ruleset = alt1 / alt2 / alt3 / alt4 / alt5

等价于

ruleset = alt1 / alt2  
ruleset =/ alt3  
ruleset =/ alt4 / alt5  
  • 值范围%c##-##

%c##-##

数值范围可以通过使用连字符(“-”)来指定。

OCTAL = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7"

等价于

OCTAL = %x30-37
  • 序列组合

(Rule1 Rule2)

被括号包围起来的一组规则,被视为单个元素。

group = a (b / c) d  

表示匹配 “a b d” 或者 “a c d”。

  • 不定量重复m*n

m*nRule

m: 元素的最小数量

n: 元素的最大数量,默认为无限大

  • 定量重复n

nRule

Rule的数量为n

  • 可选序列

[Rule]

表示可选元素。

核心规则

RuleFormal definitionMeaning
ALPHA%x41–5A / %x61–7AUpper- and lower-case ASCII letters (A–Z, a–z)
DIGIT%x30–39Decimal digits (0–9)
HEXDIGDIGIT / “A” / “B” / “C” / “D” / “E” / “F”Hexadecimal digits (0–9, A–F, a-f)
DQUOTE%x22Double quote
SP%x20Space
HTAB%x09Horizontal tab
WSPSP / HTABSpace and horizontal tab
LWSP*(WSP / CRLF WSP)Linear white space (past newline)
VCHAR%x21–7EVisible (printing) characters
CHAR%x01–7FAny ASCII character, excluding NUL
OCTET%x00–FF8 bits of data
CTL%x00–1F / %x7FControls
CR%x0DCarriage return
LF%x0ALinefeed
CRLFCR LFInternet-standard newline
BIT“0” / “1”Binary digit

HTTP协议的描述

HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body ]
- start-line = request-line / status-line
  - request-line = method SP request-target SP HTTP-version CRLF
  - status-line = HTTP-version SP status-code SP reason-phrase CRLF
- header-field = field-name ":" OWS field-value OWS
  - OWS = *( SP / HTAB )
  - field-name = token
  - field-value = *( field-content / obs-fold )
- message-body = *OCTET

请求和响应都可以携带包体,定长包体的传输需要使用Content-Length头部指明包体长度,不定长包体需要指明Transfer-Encoding。含有Transfer-Encoding头部后Content-Length头部应该被忽略。

- Transfer-Encoding = 1#transfer-coding
  - transfer-coding = "chunked" / "compress" /"deflate"  / "gzip" / transfer-extension
    - transfer-extension = token *( OWS ";" OWS transfer-parameter )

transfer-parameter = token BWS "=" BWS ( token / quoted-string )

分块传输编码:

Transfer-Encoding: chunked
- chunked-body   = *chunk
                last-chunk
                trailer-part
                CRLF
- chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF
  - chunk-size = 1*HEXDIG
  - chunk-data = 1*OCTET
- last-chunk = 1*("0") [ chunk-ext ] CRLF
- trailer-part = *( header-field CRLF )

我们来看看一个具体的http报文,这些定义都对应于哪些内容。

  GET /hello.txt HTTP/1.1
  User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
  Host: www.example.com
  Accept-Language: en, mi

  HTTP/1.1 200 OK
  Date: Mon, 27 Jul 2009 12:28:53 GMT
  Server: Apache
  Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
  ETag: "34aa387-d-1568eb00"
  Accept-Ranges: bytes
  Content-Length: 51
  Vary: Accept-Encoding
  Content-Type: text/plain

  Hello World! My payload includes a trailing CRLF.

request-line:

GET /hello.txt HTTP/1.1

status-line:

HTTP/1.1 200 OK

header-field:

Host: www.example.com
Server: Apache
Date: Mon, 27 Jul 2009 12:28:53 GMT

message-body:

Hello World! My payload includes a trailing CRLF.

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值