• python http.server 的测试和常见问题解决方法


    一.测试准备

    先分别写一个简单httpserver 和一个html文件。html文件只是引入了 jquery, 后面测试用

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Titletitle>
    6. <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js">script>
    7. head>
    8. <body>
    9. body>
    10. html>

    python 是开启了最简单的一个 http服务 

    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3. # Project: httpserver_test
    4. # File : main.py
    5. # Author : Long.Xu
    6. # http://gnolux.blog.csdn.net
    7. # QQ:26564303 weixin:wxgnolux
    8. # Time : 2022/8/27 17:19
    9. # Copyright 2022 Long.Xu All rights Reserved.
    10. from http.server import BaseHTTPRequestHandler, test
    11. import os
    12. class TestRequestHandler(BaseHTTPRequestHandler):
    13. def do_GET(self):
    14. print("do_GET")
    15. if self.path == '/':
    16. txt = "do_GET Test body"
    17. self.send_response_only(200)
    18. self.send_header('Content-type', 'text/html')
    19. self.end_headers()
    20. self.wfile.write(txt.encode())
    21. else:
    22. self.send_error(404)
    23. if __name__ == '__main__':
    24. test(HandlerClass=TestRequestHandler)

    python 脚本运行,会开启 127.0.0.1:8000   的http服务。

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

    好了,在这个基础上我们来研究和测试几个问题。

    二.测试问题1: 跨域访问问题

    我们单独以文件方式打开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里加入一个访问许可标识。如下:

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

     三.测试其它HTTP动作

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

    首先是做了一个 OPTIONS 方法的请求,反回没有这个方法,也就是说除了get外其它方法(动作)首先会先做一个OPTIONS 的请求,来确认请求的动作是不是被允许的。 所以要先实作 OPTIONS动作。 python脚本加上以下代码:

    1. def do_OPTIONS(self):
    2. print("do_OPTIONS")
    3. self.send_response_only(200, "ok")
    4. self.send_header('Access-Control-Allow-Origin', '*')
    5. self.end_headers()

    再测试:

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

    1. def do_OPTIONS(self):
    2. print("do_OPTIONS")
    3. self.send_response_only(200, "ok")
    4. self.send_header('Access-Control-Allow-Origin', '*')
    5. self.send_header('Access-Control-Allow-Methods', 'PUT')
    6. self.end_headers()

     再测试,如下,成功了。

    我们再扩展一下思路,是不是只要在这里定义好允许的动作,我们可以随意定义超出http标准的动作呢。我们试一下,加一个TEST01动作,并实作一个 do_TEST01

    self.send_header('Access-Control-Allow-Methods', 'PUT,TEST01'

     

     

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

     三. 终端显示不想显示下面的log提示怎么办? 

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

     四.http.server 里几个类的关系

     首先看 Server ,  Server 的职责是完成网络通信协议的基本功能,即底层通信有它负责,那么相应的 RequestHandler 就是负责协议以上的对接收数据的处理了。
    Server 有 HTTPServer 是从TCPServer继承来的,ThreadingHTTPServer 对是继承自 HTTPServer,在它基础上增加了多线程处理机制,可以并行接收多客户端的请求。

    ReqeustHandler 有 BaseHTTPRequestHandler 和 SimpleHTTPRequestHandler 后者实作了一些对文件的处理,完成了一般httpserver对文件的访问功能。

    五.为什么 只要用 do_XXXX 的方式作一个方法,就能处理相应的方法请求呢?

    这个奥秘就在于 BaseHTTPRequestHandler 里了。

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

  • 相关阅读:
    【QT开发(11)】QT 线程QThread
    云计算——虚拟化技术Docker网络管理及数据存储
    【论文阅读】ACM MM 2023 PatchBackdoor:不修改模型的深度神经网络后门攻击
    儿童剧本杀兴起,为少儿教育增色还是添乱?
    【MyBatis笔记12】MyBatis中二级缓存相关配置内容
    华为OD机考:0030-0031-n*n数组中二进制的最大数、整数的连续自然数之和
    八 动手学深度学习v2 ——卷积神经网络之卷积+填充步幅+池化+LeNet
    私有仓库Harbor安装
    kubeadm安装kubernetes
    一种实用的边的存储结构--链式前向星
  • 原文地址:https://blog.csdn.net/fangkailove/article/details/126560585