BaseHTTPRequestHandler模塊和WSGI相關(guān)

開(kāi)發(fā)服務(wù)器BaseHTTPRequestHandler模塊

正向代理百度的例子,感受一下

# -*- coding:utf-8 -*-

import BaseHTTPServer
import hashlib
import os
import urllib2


class CacheHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        m = hashlib.md5()
        m.update(self.path)
        cache_filename = m.hexdigest()
        if os.path.exists(cache_filename):
            print "Cache hit"
            data = open(cache_filename).readlines()
        else:
            print "Cache miss"
            data = urllib2.urlopen("http://www.baidu.com" + self.path).readlines()
            open(cache_filename, 'wb').writelines(data)
        self.send_response(200)
        self.end_headers()
        self.wfile.writelines(data)


def run():
    server_address = ('0.0.0.0', 9000)
    httpd = BaseHTTPServer.HTTPServer(server_address, CacheHandler)
    httpd.serve_forever()


if __name__ == '__main__':
    run()

  • SocketService
    從最先的父類中,可以看出簡(jiǎn)單的處理流程,接受三個(gè)參數(shù),從setup->handle->finish
class BaseRequestHandler:
    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()
        finally:
            self.finish()
    def setup(self):
        pass
    def handle(self):
        pass
    def finish(self):
        pass
  • StreamRequestHandler類中
    完成基本運(yùn)行上下文,set_up
    創(chuàng)建self.rfile,self.wfile類文件對(duì)象
    self.request為socket._scoketobject
 def setup(self):
        self.connection = self.request
        if self.timeout is not None:
            self.connection.settimeout(self.timeout)
        if self.disable_nagle_algorithm:
            self.connection.setsockopt(socket.IPPROTO_TCP,
                                       socket.TCP_NODELAY, True)
        self.rfile = self.connection.makefile('rb', self.rbufsize)
        self.wfile = self.connection.makefile('wb', self.wbufsize)

    def finish(self):
        if not self.wfile.closed:
            try:
                self.wfile.flush()
            except socket.error:
                # An final socket error may have occurred here, such as
                # the local error ECONNABORTED.
                pass
        self.wfile.close()
        self.rfile.close()
  • BaseHTTPRequestHandler
    self.parse_request()
    處理暴露出鉤子
    mname = 'do_' + self.command

-回到最開(kāi)始的自定義類中
顯然他的鉤子是do_GET

此外 django的WSGIRequestHandler,用于開(kāi)發(fā)服務(wù)器

線上服務(wù)器

WSGI理解

全稱:web server Gateway Interface
其中web server是指服務(wù)器(apache,nginx),Gateway(網(wǎng)關(guān)),interface(接口)
中文:Python應(yīng)用程序(或框架)和Web服務(wù)器之間的接口規(guī)范!
作用:wsgi是將web server參數(shù)python化,封裝為request對(duì)象傳遞給$apllication$命名的函數(shù)并接受其傳出的response參數(shù),
其作用的過(guò)程如下:
Nginx,WSGI,F(xiàn)lask 之間的對(duì)話。
Nginx:Hey,WSGI,我剛收到了一個(gè)請(qǐng)求,我需要你作些準(zhǔn)備,然后由Flask來(lái)處理這個(gè)請(qǐng)求。
WSGI:OK,Nginx。我會(huì)設(shè)置好環(huán)境變量,然后將這個(gè)請(qǐng)求傳遞給Flask處理。
Flask:Thanks WSGI!給我一些時(shí)間,我將會(huì)把請(qǐng)求的響應(yīng)返回給你。
WSGI:Alright,那我等你。
Flask:Okay,我完成了,這里是請(qǐng)求的響應(yīng)結(jié)果,請(qǐng)求把結(jié)果傳遞給Nginx。
WSGI:Good job!Nginx,這里是響應(yīng)結(jié)果,已經(jīng)按照要求給你傳遞回來(lái)了。
Nginx:Cool,我收到了,我把響應(yīng)結(jié)果返回給客戶端。大家合作愉快~

具體的application

def application(#接收兩個(gè)參數(shù)
        #字典對(duì)象,包含類似CGI的環(huán)境參數(shù),從客戶端接收過(guò)來(lái)的請(qǐng)求有server填充
        environ,
        #start_response是一個(gè)回調(diào)函數(shù),由server提供.用來(lái)發(fā)送HTTP status和header給server
        start_response):

    #響應(yīng)體
    response_body = "The request method was %s" % environ['REQUEST_METHOD']
    #狀態(tài)碼
    status = "200 OK"
    
    #響應(yīng)頭
    response_headers = [('Content-Type':'text/plain'),
                        ('Content-Length':str(len(response_body)))]
    #發(fā)送給server
    start_response(status, response_headers)

    #把響應(yīng)體返回給server
    #注意:盡管response_body是一個(gè)iterable,但是要包裝成list,否則server會(huì)單個(gè)字節(jié)的發(fā)送給client.
    return [response_body]

來(lái)一段django中的WSGIHandler實(shí)際例子

class WSGIHandler(base.BaseHandler):
    initLock = Lock()
    request_class = WSGIRequest

    def __call__(self, environ, start_response):
        # Set up middleware if needed. We couldn't do this earlier, because
        # settings weren't available.
        if self._request_middleware is None:
            with self.initLock:
                try:
                    # Check that middleware is still uninitialized.
                    if self._request_middleware is None:
                        # 加載中間件
                        self.load_middleware()
                except:
                    # Unload whatever middleware we got
                    self._request_middleware = None
                    raise

        set_script_prefix(get_script_name(environ))
        signals.request_started.send(sender=self.__class__, environ=environ)
        try:
            # 形成request對(duì)象
            request = self.request_class(environ)
        except UnicodeDecodeError:
            logger.warning('Bad Request (UnicodeDecodeError)',
                exc_info=sys.exc_info(),
                extra={
                    'status_code': 400,
                }
            )
            response = http.HttpResponseBadRequest()
        else:
            response = self.get_response(request)

        response._handler_class = self.__class__

        status = '%s %s' % (response.status_code, response.reason_phrase)
        response_headers = [(str(k), str(v)) for k, v in response.items()]
        for c in response.cookies.values():
            response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
            # #把響應(yīng)體返回給server
        start_response(force_str(status), response_headers)
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
            # 返回內(nèi)容
        return response

參考

https://www.zhihu.com/question/19998865
http://blog.csdn.net/lihao21/article/details/52304119
https://github.com/lzjun567/note/blob/master/note/python/wsgi.md
https://www.fullstackpython.com/wsgi-servers.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容