如何使用 python 的 BaseHTTPServer / SimpleHTTPServer 调试 POST 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12731207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:43:40  来源:igfitidea点击:

How can I debug POST requests with python's BaseHTTPServer / SimpleHTTPServer?

pythonhttpcommand-line

提问by cwd

I found a script on this sitefor running a simple server via the command line with python.

我在这个站点上找到了一个脚本,用于通过命令行使用 python 运行一个简单的服务器。

I added some printlines in because I'd like to print out the GET and POST parameters via the command line for requests, but I can't seem to get them to show up anywhere.

我添加了一些print行,因为我想通过命令行打印请求的 GET 和 POST 参数,但我似乎无法让它们显示在任何地方。

If I just print our our the svariable (pprint (vars(s))) I end up seeing this:

如果我只是打印我们的s变量 ( pprint (vars(s))),我最终会看到:

{'client_address': ('127.0.0.1', 53373),
 'close_connection': 1,
 'command': 'GET',
 'connection': <socket._socketobject object at 0x10b6560c0>,
 'headers': <mimetools.Message instance at 0x10b689ab8>,
 'path': '/favicon.ico',
 'raw_requestline': 'GET /favicon.ico HTTP/1.1\r\n',
 'request': <socket._socketobject object at 0x10b6560c0>,
 'request_version': 'HTTP/1.1',
 'requestline': 'GET /favicon.ico HTTP/1.1',
 'rfile': <socket._fileobject object at 0x10b6538d0>,
 'server': <BaseHTTPServer.HTTPServer instance at 0x10b6893f8>,
 'wfile': <socket._fileobject object at 0x10b6536d0>}

I tried to then use the printcommand with each of the indices, (pprint (vars(s.connection))) but that's not working.

然后我尝试将print命令与每个索引 ( pprint (vars(s.connection))) 一起使用,但这不起作用。

Here is the modified script:

这是修改后的脚本:

#!/usr/bin/python
import time
import BaseHTTPServer
from pprint import pprint

HOST_NAME = 'localhost' # !!!REMEMBER TO CHANGE THIS!!!
PORT_NUMBER = 9000 # Maybe set this to 9000.


class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
        def do_HEAD(s):
                s.send_response(200)
                s.send_header("Content-type", "text/html")
                s.end_headers()
        def do_GET(s):
                """Respond to a GET request."""
                s.send_response(200)
                s.send_header("Content-type", "text/html")
                s.end_headers()
                s.wfile.write("<html><head><title>Title goes here.</title></head>")
                s.wfile.write("<body><form action='.' method='POST'><input name='x' value='1' /><input type='submit' /></form><p>This is a test.</p>")
                # If someone went to "http://something.somewhere.net/foo/bar/",
                # then s.path equals "/foo/bar/".
                s.wfile.write("<p>GET: You accessed path: %s</p>" % s.path)
                s.wfile.write("</body></html>")
                pprint (vars(s))
        def do_POST(s):
                """Respond to a POST request."""
                s.send_response(200)
                s.send_header("Content-type", "text/html")
                s.end_headers()
                s.wfile.write("<html><head><title>Title goes here.</title></head>")
                s.wfile.write("<body><p>This is a test.</p>")
                s.wfile.write("<body><form action='.' method='POST'><input type='text' name='xxxxxxxxxxxx' value='0000000000000000000000' /><input type='submit' /></form><p>This is a test.</p>")
                # If someone went to "http://something.somewhere.net/foo/bar/",
                # then s.path equals "/foo/bar/".
                s.wfile.write("<p>POST: You accessed path: %s</p>" % s.path)
                s.wfile.write("</body></html>")
                pprint (vars(s))
                pprint (vars(s.connection))
                pprint (vars(s.headers))
                pprint (vars(s.request))
                pprint (vars(s.rfile))
                pprint (vars(s.server))
                pprint (vars(s.wfile))
                pprint (vars(s.fp))
                """pprint (vars(s.request))"""

if __name__ == '__main__':
        server_class = BaseHTTPServer.HTTPServer
        httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)
        print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)
        try:
                httpd.serve_forever()
        except KeyboardInterrupt:
                pass
        httpd.server_close()
        print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)

How can I print out POST and GET parameters using a simple script?

如何使用简单的脚本打印 POST 和 GET 参数?

Desired output via the command line would look something like:

通过命令行所需的输出如下所示:

1.0.0.127. - - [03/Oct/2012 16:02:05] "POST / HTTP/1.1" 200 -
foo=1
bar=2
bis=3

采纳答案by ire_and_curses

It's not tremendously obvious, but the handler is using sockets behind the scenes. So you need to read the raw data from the socket, and then interpret it.

这不是很明显,但处理程序在幕后使用套接字。所以你需要从socket中读取原始数据,然后解释它。

Use the urlparsemodule.

使用urlparse模块。

  • In Python 2, you want urlparse.parse_qs.
  • In Python 3, the library is renamed: you want urllib.parse.parse_qs.
  • 在 Python 2 中,您需要urlparse.parse_qs.
  • 在 Python 3 中,库被重命名:你想要urllib.parse.parse_qs.

Import urlparse, and then modify your do_POSTmethod like so:

导入urlparse,然后do_POST像这样修改你的方法:

def do_POST(s):
        """Respond to a POST request."""

        # Extract and print the contents of the POST
        length = int(s.headers['Content-Length'])
        post_data = urlparse.parse_qs(s.rfile.read(length).decode('utf-8'))
        for key, value in post_data.iteritems():
            print "%s=%s" % (key, value)

        s.send_response(200)
        s.send_header("Content-type", "text/html")
        s.end_headers()
        ...

Set up a simple test client:

设置一个简单的测试客户端:

#!/usr/bin/env python

import urllib
import urllib2

url = 'http://localhost:9000'
post_dict = {'foo' : 1,
             'bar' : 2,
             'bis' : 3}

params = urllib.urlencode(post_dict)
post_req = urllib2.Request(url)
post_req.add_data(params)

response = urllib2.urlopen(post_req)
response_data = response.read()
response.close()
print response_data

Start the server, and then run the client:

启动服务器,然后运行客户端:

ire@localhost$ python http_server.py 
Wed Oct  3 21:38:51 2012 Server Starts - localhost:9000
foo=[u'1']
bar=[u'2']
bis=[u'3']

回答by Nowaker

You can use cgimodule instead of urlparse. cgiimplements POST params parsing out of the box. Using well-tested libraries seems better.

您可以使用cgimodule 代替urlparse. cgi实现开箱即用的 POST 参数解析。使用经过良好测试的库似乎更好。

import cgi

import cgi

def do_POST(self):
    form = cgi.FieldStorage(
        fp=self.rfile,
        headers=self.headers,
        environ={"REQUEST_METHOD": "POST"}
    )

    for item in form.list:
        print "%s=%s" % (item.name, item.value)