【问题标题】:Parsing GET request data with from SimpleHTTPServer使用 SimpleHTTPServer 解析 GET 请求数据
【发布时间】:2014-08-14 19:23:41
【问题描述】:

所以我通过这样做在 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 数据,例如 URL、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 数据库中。

【问题讨论】:

  • 您是要保存已解析的日志还是要执行其他操作?
  • @slipjack 我想保存日志将是一个好的开始。
  • @slipjack 我想一个更好的方式来放置我正在寻找的内容是我想在 GET 请求进入时对其进行解析。
  • 你会从使用像flask这样的更高级别的库中受益匪浅。
  • 实际命令如GET HTTP/1.1 /crazysean/?url=www.google.com&x=200&y=400。您可以通过子类化处理程序来获得其中的一部分。如果您想要其余的日志信息,例如 301,那不是请求的一部分;那就是解释它对请求做了什么的处理程序。

标签: python simplehttpserver


【解决方案1】:

认为这是一个 XY 问题。您对解析 GET 请求或对日志做任何事情没有兴趣;您想要的是“捕获 GET 数据”,就像 SimpleHTTPServer 使用该数据来处理请求一样,因此您可以将其存储在数据库中。而您只是认为唯一的方法是解析 somethingsomewhere,但您不确定是什么。

很明显,SimpleHTTPServer 必须已经在解析GET 数据,并且必须有您想要的可用数据。那么,它在哪里呢?

正如the docs 在顶部所说:

很多工作,比如解析请求,都是由基类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 请求的一部分,而是套接字连接的一部分的信息,或有关服务器的信息等,也有相应的属性。

【讨论】:

  • 这是一个很好的答案,非常感谢。我以前从未使用过课程,所以我有一些研究要做。
猜你喜欢
  • 2020-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多