使用SimpleHTTPServer解析GET请求数据

1 投票
1 回答
10306 浏览
提问于 2025-04-18 17:19

我在一台运行Ubuntu的电脑上创建了一个简单的服务器,使用的是8000这个端口,方法很简单:

python -m SimpleHTTPServer

10.127.11.18 - - [14/Aug/2014 15:11:55] "GET / HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:11:55] code 404, message File not found
10.127.11.18 - - [14/Aug/2014 15:11:55] "GET /favicon.ico HTTP/1.1" 404 -
10.127.11.18 - - [14/Aug/2014 15:12:02] "GET /crazysean/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:12:37] "GET /crazysean/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:12:52] "GET /crazysean/?url=www.google.com&x=200&y=400 HTTP/1.1" 301 -
10.127.11.18 - - [14/Aug/2014 15:12:52] "GET /crazysean/?url=www.google.com&x=200&y=400/ HTTP/1.1" 200 -
10.127.11.18 - - [14/Aug/2014 15:13:10] "GET /crazysean/?url=www.google.com&x=200&y=400/ HTTP/1.1" 200 -

我想提取发送过来的GET数据,比如网址、x坐标和y坐标。

我想第一步应该是创建一个新的脚本,像这样:

import SimpleHTTPServer
import SocketServer

PORT = 8000

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()

但是我不太确定该怎么修改这个脚本来获取GET数据,因为最后我想把这些数据存到一个sqlite3数据库里。

1 个回答

5

我觉得这可能是个XY问题。你其实并不想去解析GET请求,也不想处理日志;你真正想要的是“捕获GET数据”,就像SimpleHTTPServer那样使用这些数据来响应请求,然后把它存储到数据库里。你只是觉得唯一的办法就是去解析某些东西某个地方,但你不太确定是什么。

显然,SimpleHTTPServer已经在解析GET数据,并且它一定有你想要的东西。那么,这些数据在哪里呢?

正如文档开头所说:

很多工作,比如解析请求,都是由基类BaseHTTPServer.BaseHTTPRequestHandler完成的。这个类实现了do_GET()do_HEAD()函数。

点击那个链接,你会看到:

处理程序会解析请求和头部,然后调用一个特定于请求类型的方法。方法名是根据请求构造的。例如,对于请求方法SPAM,会调用do_SPAM()方法,没有参数。所有相关的信息都存储在处理程序的实例变量中……

所以,所有内容都已经解析到实例变量里;在那段话下面有一个很好的变量列表。

所以:

class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super(DBLoggingHandler, self).__init__(*args, **kwargs)
        self.db = sqlite3.connect(dbpath)
    def do_GET(self):
        self.db.execute("INSERT INTO GetLog (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        return super(DBLoggingHandler, self).do_GET()

如果你想把path解析成不同的部分,可以使用urlparse来实现:

    def do_GET(self):
        bits = urlparse.urlpase(self.path)
        self.db.execute("""INSERT INTO GetLog (command, vers, scheme, netloc, 
                                               path, params, query, fragment,
                                               username, password, hostname, port)
                           VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
                        (self.command, self.request_version, bits.scheme, bits.netloc,
                         bits.path, bits.params, bits.query, bits.fragment,
                         bits.username, bits.password, bits.hostname, bits.port))
        return super(DBLoggingHandler, self).do_GET()

另外,记住请求不仅仅有命令行;它们通常还有头部,并且可能有主体(虽然对于GET请求通常没有)。可以查看headersrfile。还有一些信息不是HTTP请求的一部分,而是套接字连接的信息,或者关于服务器的信息等等,这些也有相应的属性。

撰写回答