netkit/http/parser

这个模块实现了一个增量的 HTTP 消息解析器。该解析器支持解析请求消息和响应消息。

解析器是增量的,这表示可以连续解析消息,而不管消息是一次交付还是分成多个部分。这使得该解析器特别适合复杂的 IO 传输环境。

用法

解析消息头

例子:

import netkit/http/parser
import netkit/http/header
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var header = HttpHeader(kind: HttpHeaderKind.Request)
var finished = false

while not finished:
  put data to buffer ...
  finished = parser.parseHttpHeader(buffer, header)

另一个例子:

import netkit/http/parser
import netkit/http/header
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var header = HttpHeader(kind: HttpHeaderKind.Request)

# 第一次解析
let messageRequestLine = "GET / HTTP/1.1\r\n"
buffer.add(messageRequestLine.cstring, messageRequestLine.len)
assert parser.parseHttpHeader(buffer, header) == false
buffer.del(messageRequestLine.len)

# 第二次解析
let messageHeaderFields = "Host: www.iocrate.com\r\n\r\n"
buffer.add(messageHeaderFields.cstring, messageHeaderFields.len)
assert parser.parseHttpHeader(buffer, header) == true
buffer.del(messageHeaderFields.len)

assert header.reqMethod == HttpGet
assert header.url == "/"
assert header.version.orig == "HTTP/1.1"
assert header.fields["Host"][0] == "www.iocrate.com"

解析 chunked 编码消息的块的头部

例子:

import netkit/http/parser
import netkit/http/chunk
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var header: ChunkHeader
var finished = false

while not finished:
  put data to buffer ...
  finished = parser.parseChunkHeader(buffer, header)

另一个例子:

import netkit/http/parser
import netkit/http/chunk
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var header: ChunkHeader

let s = "9; language=en; city=London\r\n"
buffer.add(s.cstring, s.len)
assert parser.parseChunkHeader(buffer, header) == true
buffer.del(s.len)

assert header.size == 9
assert header.extensions == "; language=en; city=London"

See chunk module and metadata module for more information about chunked encoding.

例子:

import netkit/http/parser
import netkit/http/chunk
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var trailers: seq[string]
var finished = false

while not finished:
  put data to buffer ...
  finished = parser.parseChunkEnd(buffer, trailers)

另一个例子:

import netkit/http/parser
import netkit/http/chunk
import netkit/buffer/circular

var parser = initHttpParser()
var buffer = initMarkableCircularBuffer()
var trailers: seq[string]

let s = "\0\r\nExpires": "Wed, 21 Oct 2015 07:28:00 GMT\r\n\r\n"
buffer.add(s.cstring, s.len)
assert parser.parseChunkEnd(buffer, trailers) == true
buffer.del(s.len)

assert trailers[0] == "Expires": "Wed, 21 Oct 2015 07:28:00 GMT"

看看 chunk 模块和 metadata 模块了解更多关于 terminating chunk and trailers 的信息。

Types

HttpParser = object
  secondaryBuffer: string
  currentLineLen: Natural
  currentFieldName: string
  currentFieldCount: Natural
  state: HttpParseState
  startLineState: StartLineState
HTTP 消息解析器。   Source Edit

Procs

proc initHttpParser(): HttpParser {...}{.raises: [], tags: [].}
初始化一个 HttpParser 。   Source Edit
proc clear(p: var HttpParser) {...}{.raises: [], tags: [].}

重置解析器以清除所有状态。

由于解析器是增量的,因此在解析过程中将保存许多状态。此函数将重置所有状态,以开始新的解析过程。

  Source Edit
proc parseHttpHeader(p: var HttpParser; buf: var MarkableCircularBuffer;
                    header: var HttpHeader): bool {...}{.raises: [], tags: [].}

解析 HTTP 消息的头部。 buf 指定一个循环缓冲区,存储被解析的数据。 header 指定解析完成时输出的消息标头对象。 如果解析完成,则返回 true

根据 headerkind 属性值,采用不同的解析方案。当 kind = Request 时,消息被解析为请求。当 kind = Response 时,消息被解析为响应。

此过程是增量执行的,也就是说,下一次解析将从上一次结束的位置继续。

  Source Edit
proc parseChunkHeader(p: var HttpParser; buf: var MarkableCircularBuffer;
                     header: var ChunkHeader): bool {...}{.raises: [], tags: [].}

解析通过 chunked 编码消息的块的头部(大小和扩展名)。

此过程是增量执行的,也就是说,下一次解析将从上一次结束的位置继续。

  Source Edit
proc parseChunkEnd(p: var HttpParser; buf: var MarkableCircularBuffer;
                  trailers: var seq[string]): bool {...}{.raises: [], tags: [].}

解析通过 chunked 编码消息的尾部(终止块、trailers、final CRLF)。

此过程是增量执行的,也就是说,下一次解析将从上一次结束的位置继续。

  Source Edit