python 和 BaseHTTPRequestHandler :在生成的页面的标题中添加一个空的图标

问题描述

在 python 3.8 上,我使用模块 http.server 中的 BaseHTTPRequestHandler 和 HTTPServer 为我的学生创建了一个极简的 python 服务器

当我去服务器上的url时,在浏览器调试工具中看到两个http请求:

enter image description here

我想阻止第二个请求(对于网站图标)。我的问题是:使用“BaseHTTPRequestHandler”和“HTTPServer”类是否可以自定义生成页面标题?我正在寻找一种方法添加这样的空图标:<link rel="icon" href="data:;base64,="> (https://stackoverflow.com/a/13416784/2137454)

解决方法

这显然是可能的。毕竟,您可以完全控制服务器向客户端发送的内容。但是,我认为您不应该这样做。只需提供那个烦人的小文件 favicon.ico。这是最简单的方法:

import socketserver
from http.server import SimpleHTTPRequestHandler


class CustomHttpRequestHandler(SimpleHTTPRequestHandler):

    def do_GET(self):
        if self.path == '/':
            # here do whatever your custom server would normally do
            self.path = 'static/index.html'

        if self.path == '/favicon.ico':
            self.path = 'static/favicon.ico'

        return SimpleHTTPRequestHandler.do_GET(self)


if __name__ == '__main__':
    PORT = 8001
    my_server = socketserver.TCPServer(("",PORT),CustomHttpRequestHandler)
    my_server.serve_forever()

要完成这项工作,您需要做的就是在文件夹 static 中放置一个 png 文件并将其命名为 favicon.ico

当然,您也可以修改您发送的 html 内容。由于您的问题中没有代码,我一起进行了一个小模拟:

import socketserver
from http.server import SimpleHTTPRequestHandler
import io

favicon = '<link rel="icon" href="data:;base64,=">\n'


class CustomHttpRequestHandler(SimpleHTTPRequestHandler):

    def do_GET(self):
        if self.path == '/':
            self.path = 'index.html'

        f = self.send_head()  # f is the file to send or None

        # following code will break easily. don't do this...
        content = ""
        for line in f:
            line = line.decode("utf8")
            # 'parsing' html like this is really a bad idea. don't do it...
            if "</head>" in line:
                content += favicon
            content += line

        f2 = io.BytesIO(content.encode("utf-8"))
        self.copyfile(f2,self.wfile)


if __name__ == '__main__':
    PORT = 8001
    my_server = socketserver.TCPServer(("",CustomHttpRequestHandler)
    my_server.serve_forever()

这里我假设您正在提供当前目录中的静态文件。在将其发送给客户端之前,<link rel="icon"> 标记会附加在结束 <head> 标记之前。当然,这很容易破裂。 但是,如果您确实要生成 html 而不是提供静态文件,则在代码中放置 content += favicon 行可能很简单且省钱。

,

在您的 do_GET 中,添加以下 else if 条件:

elif self.path == '/favicon.ico':
    self.send_response(200)
    self.send_header('Content-Type','image/x-icon')
    self.send_header('Content-Length',0)
    self.end_headers()

这将抑制控制台错误,因为 Chrome 认为它已收到收藏夹图标 - 即使它是具有正确内容类型和响应代码的 0 字节响应。