4

Fasthttp系列——请求行

 2 years ago
source link: https://kiyonlin.github.io/post/work/fasthttp/01fh%E8%AF%B7%E6%B1%82%E8%A1%8C/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Fasthttp系列——请求行

2020-08-18 约 994 字 预计阅读 2 分钟

本系列通过解析fasthttp(v1.16.0)源码学习HTTP/1.1

WEB服务接收HTTP请求要做的第一件事,就是解析请求行(Request Line)。它的格式如下:

request-line   = method SP request-target SP HTTP-version CRLF

对应到fasthttp中的代码是:

func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) {
	bNext := buf
	var b []byte
	var err error
	for len(b) == 0 {
		if b, bNext, err = nextLine(bNext); err != nil {
			return 0, err
		}
	}

	// parse method
	n := bytes.IndexByte(b, ' ')
	if n <= 0 {
		return 0, fmt.Errorf("cannot find http request method in %q", buf)
	}
	h.method = append(h.method[:0], b[:n]...)
	b = b[n+1:]

	// parse requestURI
	n = bytes.LastIndexByte(b, ' ')
	if n < 0 {
		h.noHTTP11 = true
		n = len(b)
	} else if n == 0 {
		return 0, fmt.Errorf("requestURI cannot be empty in %q", buf)
	} else if !bytes.Equal(b[n+1:], strHTTP11) {
		h.noHTTP11 = true
	}
	h.requestURI = append(h.requestURI[:0], b[:n]...)

	return len(buf) - len(bNext), nil
}

我们可以看到fasthttp先调用nextLine方法,根据分隔符(\r\n)获取出第一行的所有字节数据b

再根据b中第一个空格字节的位置解析出method,存入请求头对象中h.method = append(h.method[:0], b[:n]...)

再根据b中最后一个空格的位置,解析出request-targetHTTP-version

其中HTTP-versionh.noHTTP11保存一个bool值,不存在HTTP版本数据或者它不等于HTTP/1.1时,这个字段都为false

request-target也是直接保存到请求头对象中h.requestURI = append(h.requestURI[:0], b[:n]...)

最后返回第一行的字节数,done!

The method token indicates the request method to be performed on the target resource. The request method is case-sensitive.

我们注意到RFC中有提到请求method是大小写敏感的(The request method is case-sensitive)。

而且根据上面的解析过程,我们可以看出fasthttp获取到method时,直接保存在请求头中,并没有做任何检查。所以当请求端发送了不正确(比如用了小写)的method值时,服务端可以拒绝这次请求(400 Bad Request)。

所有的请求method可以在RFC7231中查看,之后也会细讲。

客户端发送HTTP请求消息时,其中包含从目标URI派生的请求目标。请求目标有四种不同的格式,具体取决于请求的方法以及请求是否针对代理:

  request-target = origin-form
                 / absolute-form
                 / authority-form
                 / asterisk-form

之后的文章会针对请求目标做详细的分析,这里不再赘述。

本系列的第一篇文章就这样结束了。我们了解了请求行的结构,并剖析了fasthttp是如何从数据流中解析这第一行请求数据。

敬请期待之后的系列文章! 👋


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK