先分别写一个简单httpserver 和一个html文件。html文件只是引入了 jquery, 后面测试用
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Titletitle>
- <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
- head>
- <body>
-
- body>
- html>
python 是开启了最简单的一个 http服务
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
-
- # Project: httpserver_test
- # File : main.py
- # Author : Long.Xu
- # http://gnolux.blog.csdn.net
- # QQ:26564303 weixin:wxgnolux
- # Time : 2022/8/27 17:19
- # Copyright 2022 Long.Xu All rights Reserved.
- from http.server import BaseHTTPRequestHandler, test
- import os
-
-
- class TestRequestHandler(BaseHTTPRequestHandler):
- def do_GET(self):
- print("do_GET")
- if self.path == '/':
- txt = "do_GET Test body"
- self.send_response_only(200)
- self.send_header('Content-type', 'text/html')
- self.end_headers()
- self.wfile.write(txt.encode())
- else:
- self.send_error(404)
-
- if __name__ == '__main__':
- test(HandlerClass=TestRequestHandler)
python 脚本运行,会开启 127.0.0.1:8000 的http服务。

浏览器访问 http://127.0.0.1:8000 ,可以正常访问,返回结果也正确。

好了,在这个基础上我们来研究和测试几个问题。
我们单独以文件方式打开html文件,并在chrome打开调试
$.ajax({url:'http://127.0.0.1:8000',type:'get',success:function (data) {
console.log(data)
}})
正常情况,应该能打印出 do_GET test body , 但实际会报错,如下:

提示因为跨域策略被阻挡了,并未按预期的正常返回信息,这是因为我们现在是以本地文件的方式,访问一个远程服务(虽然是127.0.0.1),因为服务器不支持跨域访问,那服务器要怎么处理?服务器只需要接收到此类请求时,在header里加入一个访问许可标识。如下:

修改完后,重新运行脚本,浏览器再次测试,成功。


按之前do_GET的方法,实作了do_PUT 应该是可以的,但为什么还是会报跨域的错误呢?我们看一下请求。实际上有两个请求:

首先是做了一个 OPTIONS 方法的请求,反回没有这个方法,也就是说除了get外其它方法(动作)首先会先做一个OPTIONS 的请求,来确认请求的动作是不是被允许的。 所以要先实作 OPTIONS动作。 python脚本加上以下代码:
- def do_OPTIONS(self):
- print("do_OPTIONS")
- self.send_response_only(200, "ok")
- self.send_header('Access-Control-Allow-Origin', '*')
- self.end_headers()
再测试:

可以发现 第一个请求成功了,即options方法请求成功,但是put还是没有成功,报错 PUT 方法不被允许。 这个就是要在options方法内,服务器要没有返回相应的允许的动作 ,再修改 do_OPTIONS 方法 ,加入 self.send_header('Access-Control-Allow-Methods', 'PUT')
- def do_OPTIONS(self):
- print("do_OPTIONS")
- self.send_response_only(200, "ok")
- self.send_header('Access-Control-Allow-Origin', '*')
- self.send_header('Access-Control-Allow-Methods', 'PUT')
- self.end_headers()
再测试,如下,成功了。

我们再扩展一下思路,是不是只要在这里定义好允许的动作,我们可以随意定义超出http标准的动作呢。我们试一下,加一个TEST01动作,并实作一个 do_TEST01
self.send_header('Access-Control-Allow-Methods', 'PUT,TEST01'



还真的行哦。 结论就是只要 在options里返回允许的 method,服务器段也有相应的method处理程序那么完全可以自定义 http method.

这里我们可以改用 self.send_response_only(200)
来避免,但是有些地方只能用其它方法或者是基类的log产生的log,这种方法就无没办法了。其实可以把基类中 log_message 方法给继承重写了,就能避免输出了。


首先看 Server , Server 的职责是完成网络通信协议的基本功能,即底层通信有它负责,那么相应的 RequestHandler 就是负责协议以上的对接收数据的处理了。
Server 有 HTTPServer 是从TCPServer继承来的,ThreadingHTTPServer 对是继承自 HTTPServer,在它基础上增加了多线程处理机制,可以并行接收多客户端的请求。
ReqeustHandler 有 BaseHTTPRequestHandler 和 SimpleHTTPRequestHandler 后者实作了一些对文件的处理,完成了一般httpserver对文件的访问功能。
这个奥秘就在于 BaseHTTPRequestHandler 里了。


是按前端传来的 command ,动态查找有没有相应的方法,如果有就调用的,这里充份发挥了python语言的特点了。 换作其它语言,要预做很多接口或抽象方法,在子类中实作才行吧。