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

一.测试准备

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <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 <fangkailove@yeah.net>
#          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 ,可以正常访问,返回结果也正确。

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

二.测试问题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脚本加上以下代码:

 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. 

 三. 终端显示不想显示下面的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语言的特点了。 换作其它语言,要预做很多接口或抽象方法,在子类中实作才行吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wxgnolux

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值