BaseHTTPRequestHandler

                class BaseHTTPServer.BaseHTTPRequestHandler(request,client_address, server)

This class is used to handle the HTTP requests that arrive at the server. By itself, it cannot respond to any actual HTTP requests; it must be subclassed to handle each request method (e.g. GET or POST). BaseHTTPRequestHandler provides a number of class and instance variables, and methods for use by subclasses.

PyMOTW: BaseHTTPServer

  • 模块: BaseHTTPServer
  • 目的: 提供实现web服务的基础类.
  • python版本: 1.4+

BaseHTTPServer模块包括了能够构成基本的web服务器的类.

描述

BaseHTTPServer使用 SocketServer 中的类来创建HTTP服务基本类, HTTPServer可以被直接使用, 但是其中的BaseHTTPRequestHandler需要被扩展去处理各种协议方法(如GET, POST等).

简单的GET请求例子

实现 do_METHOD() 方法可以让你的请求类支持HTTP方法, 这里的METHOD用具体的HTTP方法名字代替. 例如,do_GET(), do_POST() 等. 为了保持一致, 这些方法不含参数. 用于请求的所有的参数被BaseHTTPRequestHandler解析, 然后被存储在一个实例属性集合中, 这样你可以很方便地检索它们.

下面的例子中, 请求处理对象说明了如何返回一个响应对象给客户端, 一些本地属性在构造响应对象中很有用的.

from BaseHTTPServer import BaseHTTPRequestHandlerimport urlparseclass GetHandler(BaseHTTPRequestHandler):    def do_GET(self):        parsed_path = urlparse.urlparse(self.path)        message = '\n'.join([          'CLIENT VALUES:',          'client_address=%s (%s)' % (self.client_address, self.address_string()),          'command=%s' % self.command,          'path=%s' % self.path,          'real path=%s' % parsed_path.path,          'query=%s' % parsed_path.query,          'request_version=%s' % self.request_version,          '',          'SERVER VALUES:',          'server_version=%s' % self.server_version,          'sys_version=%s' % self.sys_version,          'protocol_version=%s' % self.protocol_version,          '',        ])        self.send_response(200)        self.end_headers()        self.wfile.write(message)        return

消息正文被组装好后就写入到self.wfile中, 这个文件处理对象封装了整个响应socket. 每个响应对象需要一个响应代码, 它可以通过self.send_response()来设置. 如果使用了一个错误代码(如404, 501等), 那么对应的默认错误信息会被包含在消息头中, 或者, 你能使用错误码来传递信息.

在服务器中运行请求处理对象, 将这个请求处理对象传递给HTTPServer构造器.

if __name__ == '__main__':    from BaseHTTPServer import HTTPServer    server = HTTPServer(('localhost', 8080), GetHandler)    print 'Starting server, use <Ctrl-C> to stop'    server.serve_forever()

接下来启动服务器:

$ python BaseHTTPServer_GET.pyStarting server, use <Ctrl-C> to stop

在另外一终端中, 使用curl访问:

$ curl -i http://localhost:8080/?foo=barHTTP/1.0 200 OKServer: BaseHTTP/0.3 Python/2.5.1Date: Sun, 09 Dec 2007 16:00:34 GMTCLIENT VALUES:client_address=('127.0.0.1', 51275) (localhost)command=GETpath=/?foo=barreal path=/query=foo=barrequest_version=HTTP/1.1SERVER VALUES:server_version=BaseHTTP/0.3sys_version=Python/2.5.1protocol_version=HTTP/1.0

线程和进程

HTTPServer是SocketServer.TCPServer的一个简单子类. 它不使用多线程或多进程来处理请求. 要增加多线程和多进程, 可以使用SocketServer中的合适的混用类来创建一个新的类.

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandlerfrom SocketServer import ThreadingMixInimport threadingclass Handler(BaseHTTPRequestHandler):    def do_GET(self):        self.send_response(200)        self.end_headers()        message = threading.currentThread().getName() ## 这里threading就可以自己处理        self.wfile.write(message)        self.wfile.write('\n')        returnclass ThreadedHTTPServer(ThreadingMixIn, HTTPServer):    """Handle requests in a separate thread."""if __name__ == '__main__':    server = ThreadedHTTPServer(('localhost', 8080), Handler)    print 'Starting server, use <Ctrl-C> to stop'    server.serve_forever()

每次当一个请求过来的时候, 一个新的线程或进程会被创建来处理它:

$ curl http://localhost:8080/Thread-1$ curl http://localhost:8080/Thread-2$ curl http://localhost:8080/Thread-3

如果把上面的ThreadingMixIn换成ForkingMixIn, 也可以获得类似的结果, 但是后者是使用了独立的进程而不是线程.

POST

支持POST请求需要多一点的工作, 因为基本类不会为我们解析表单数据. cgi 模块提供了用于解析表单的FieldStorage类,只要我们提供正确的输入格式.

from BaseHTTPServer import BaseHTTPRequestHandlerimport cgiclass PostHandler(BaseHTTPRequestHandler):    def do_POST(self):        # Parse the form data posted        form = cgi.FieldStorage(        fp=self.rfile,        headers=self.headers,        environ={'REQUEST_METHOD':'POST',          'CONTENT_TYPE':self.headers['Content-Type'],        })        # Begin the response        self.send_response(200)        self.end_headers()        self.wfile.write('Client: %s\n' % str(self.client_address))        self.wfile.write('Path: %s\n' % self.path)        self.wfile.write('Form data:\n')        # Echo back information about what was posted in the form        for field in form.keys():            field_item = form[field]            if field_item.filename:                # The field contains an uploaded file                file_data = field_item.file.read()                file_len = len(file_data)                del file_data                self.wfile.write('\tUploaded %s (%d bytes)\n' % (field, file_len))            else:                # Regular form value                self.wfile.write('\t%s=%s\n' % (field, form[field].value))        returnif __name__ == '__main__':    from BaseHTTPServer import HTTPServer    server = HTTPServer(('localhost', 8080), PostHandler)    print 'Starting server, use <Ctrl-C> to stop'    server.serve_forever()

再次使用curl, 我们可以包含表单数据, 它自动以POST方式发送. 最后的参数, -F datafile=@BaseHTTPServer_GET.py, 将文件BaseHTTPServer_GET.py的内容发送, 从而表示已从表单中读取了文件数据.

$ curl http://localhost:8080/ -F name=dhellmann -F foo=bar -F datafile=@BaseHTTPServer_GET.pyClient: ('127.0.0.1', 51128)Path: /Form data:         name=dhellmann         foo=bar         Uploaded datafile (2222 bytes)

Errors

错误处理可以使用 send_error() 方法. 简单的传递给它合适的错误代码以及一个可选的错误信息, 那么就会为你生成整个响应对象(包括头, 状态码, 消息体).

from BaseHTTPServer import BaseHTTPRequestHandlerclass ErrorHandler(BaseHTTPRequestHandler):    def do_GET(self):        self.send_error(404)        returnif __name__ == '__main__':    from BaseHTTPServer import HTTPServer    server = HTTPServer(('localhost', 8080), ErrorHandler)    print 'Starting server, use <Ctrl-C> to stop'    server.serve_forever()

在这种情况下, 一直返回404错误.

$ curl -i http://localhost:8080/HTTP/1.0 404 Not FoundServer: BaseHTTP/0.3 Python/2.5.1Date: Sun, 09 Dec 2007 15:49:44 GMTContent-Type: text/htmlConnection: close<head><title>Error response</title></head><body><h1>Error response</h1><p>Error code 404.<p>Message: Not Found.<p>Error code explanation: 404 = Nothing matches the given URI.</body>

 

           
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值