openstack swift和wsgi源码分析2 eventlet HTTP协议解析过程中rfile工作原理

openstack swift和wsgi源码分析2 eventlet HTTP协议解析过程中rfile工作原理,第1张

概述研究rfile如何解析消息头和消息正文,并返回结果的过程。 rfile和wfile 根据 client_socket 由HttpProtocal 类的setup函数生成。 生成流程,如下代码: def server(): client_socket = sock.accept()pool.spawn_n(serv.process_request, client_socket) def proce

研究rfile如何解析消息头和消息正文,并返回结果的过程。

rfile和wfile 根据 clIEnt_socket 由httpProtocal 类的setup函数生成。

生成流程,如下代码:

def server():

clIEnt_socket = sock.accept()pool.spawn_n(serv.process_request,clIEnt_socket)

def process_request(self,sock_params):

sock,address = sock_paramsproto.__init__(sock,address,self)

class BaseRequestHandler:

def __init__(self,request,clIEnt_address,server):    self.request = request    self.clIEnt_address = clIEnt_address    self.server = server

class httpProtocol

def setup(self):    conn = self.connection = self.request    try:        self.rfile = conn.makefile('rb',self.rbufsize)        self.wfile = conn.makefile('wb',self.wbufsize)    except (AttributeError,NotImplementedError):        if hasattr(conn,'send') and hasattr(conn,'recv'):            # it's an SSL.Connection            self.rfile = socket._fileobject(conn,"rb",self.rbufsize)            self.wfile = socket._fileobject(conn,"wb",self.wbufsize)

其中sock 由 eventlet 所重写的Listen函数生成,基于eventlet.greenio模块的GreenSocket 类。

self.connection调用makefile创建一个与该套接字相关连的文件

通过调试 self.rfile.readline函数(位于socket模块),可以判断python对于http的协议主要是根据数据中的/r/n分隔符,区分开消息头和消息正文,且消息正文长度由content-length消息头决定.

客户端发送数据:

POST /oauth/access_token http/1.1
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7
NSS/3.14.0.0 zlib/1.2.3 libIDn/1.18 libssh2/1.4.2
Host: localhost
Accept: /
Content-Length: 51
Content-Type: application/x-www-form-urlencoded

函数入下:

def readline(self,size=-1):    buf = self._rbuf    buf.seek(0,2)  # seek end    if buf.tell() > 0:        # check if we already have it in our buffer        buf.seek(0)        bline = buf.readline(size)        if bline.endswith('\n') or len(bline) == size:            self._rbuf = StringIO()            self._rbuf.write(buf.read())            return bline        del bline    if size < 0:        # Read until \n or EOF,whichever comes first        if self._rbufsize <= 1:            # Speed up unbuffered case            buf.seek(0)            buffers = [buf.read()]            self._rbuf = StringIO()              data = None            recv = self._sock.recv            while True:                try:                    while data != "\n":                        data = recv(1)                        if not data:                            break                        buffers.append(data)                except error,e:                    # The try..except to catch EINTR was moved outsIDe the                    # recv loop to avoID the per byte overhead.                    if _exception_was_EINTR(e):                        continue                    raise                break            return "".join(buffers)        buf.seek(0,2)  # seek end        self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.        while True:            try:                data = self._sock.recv(self._rbufsize)            except error,e:                if _exception_was_EINTR(e):                    continue                raise            if not data:                break            nl = data.find('\n')            if nl >= 0:                nl += 1                buf.write(data[:nl])                self._rbuf.write(data[nl:])                del data                break            buf.write(data)        return buf.getvalue()    else:        # Read until size bytes or \n or EOF seen,whichever comes first        buf.seek(0,2)  # seek end        buf_len = buf.tell()        if buf_len >= size:            buf.seek(0)            rv = buf.read(size)            self._rbuf = StringIO()            self._rbuf.write(buf.read())            return rv        self._rbuf = StringIO()  # reset _rbuf.  we consume it via buf.        while True:            try:                data = self._sock.recv(self._rbufsize)            except error,e:                if _exception_was_EINTR(e):                    continue                raise            if not data:                break            left = size - buf_len            # dID we just receive a newline?            nl = data.find('\n',left)            if nl >= 0:                nl += 1                # save the excess data to _rbuf                self._rbuf.write(data[nl:])                if buf_len:                    buf.write(data[:nl])                    break                else:                    # Shortcut.  AvoID data copy through buf when                    # returning                    # a substring of our first recv().                    return data[:nl]            n = len(data)            if n == size and not buf_len:                # Shortcut.  AvoID data copy through buf when                # returning exactly all of our first recv().                return data            if n >= left:                buf.write(data[:left])                self._rbuf.write(data[left:])                break            buf.write(data)            buf_len += n            #assert buf_len == buf.tell()        return buf.getvalue()

注:如果消息正文transfer-encoding:chunked 方式传输,则不实用上述解析方式。

最终消息头数据存储在self.environ变量中,消息正文由env[‘eventlet.input’]保存。

其中env[‘eventlet.input’] 的创建方式如下

env[‘wsgi.input’] =input(self.rfile,length,\
wfile=wfile,wfile_line=wfile_line,chunked_input=chunked)

若self.rfile 所读取的数据为”,则表明收到客户端答复,释放网络资源。

总结

以上是内存溢出为你收集整理的openstack swift和wsgi源码分析2 eventlet HTTP协议解析过程中rfile工作原理全部内容,希望文章能够帮你解决openstack swift和wsgi源码分析2 eventlet HTTP协议解析过程中rfile工作原理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1084573.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-27
下一篇2022-05-27

发表评论

登录后才能评论

评论列表(0条)

    保存