决定听取朋友建议找个小的web项目做做。嗯,确实是比较简单。
1. Client start TCP request; -> 2. Server accept.->
3. Client sends HTTP request containing URL. -> 4. Server receives request and sends response. ->
5. Client receives and parses response; finds links to 4 images. -> Server closes.
6. Client makes TCP to server. -> 7. Server accepts. ->
8. Client send HTTP request containing URL of first images -> ...
1.Stateless: use cookie;
2.URL can be supplemented with parameters.
1. Wait for connection and send an HTTP request;
2. Parse HTTP request;
3. Figure out what it's asking for;
4. Fetch that data;
5. Format it as HTML;
6. Send it back.
常见的请求处理有显示值、返回一个静态页面、列出目录等(CGI后面单独讲)。
可行的处理方式为:
1. 显示值 -> HTML模板;
2. 返回静态页面 -> 文件读取;
3. 列出目录 -> os库。
下面是一个HTTP返回的封装过程。
# Handle a GET request.
def do_GET(self):
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.send_header("Content-Length", str(len(self.Page)))
self.end_headers()
self.wfile.write(self.Page)
def run_cgi(self, full_path):
cmd = "python " + full_path
child_stdin, child_stdout = os.popen2(cmd)
child_stdin.close()
data = child_stdout.read()
child_stdout.close()
self.send_content(data)
class case_cgi_file(object):
'''Something runnable.'''
def test(self, handler):
return os.path.isfile(handler.full_path) and \
handler.full_path.endswith('.py')
def act(self, handler):
handler.run_cgi(handler.full_path)
重构前的代码如链接。
可以观察到,test和act函数都是各个case通用的,因此从代码结构上考虑,可以抽象出一个父类。
class base_case(object):
'''Parent for case handlers.'''
def handle_file(self, handler, full_path):
try:
with open(full_path, 'rb') as reader:
content = reader.read()
handler.send_content(content)
except IOError as msg:
msg = "'{0}' cannot be read: {1}".format(full_path, msg)
handler.handle_error(msg)
def index_path(self, handler):
return os.path.join(handler.full_path, 'index.html')
def test(self, handler):
assert False, 'Not implemented.'
def act(self, handler):
assert False, 'Not implemented.'
重构后的代码结构如链接。
如果你用的是python3,需要改动以下两点:
1. 把源码中的BaseHTTPServer换成http.server;
2. self.wfile.write(self.Page)改成self.wfile.write(self.Page.encode())