Как я могу отлаживать POST-запросы с помощью python BaseHTTPServer/SimpleHTTPServer?
Я нашел script на этот сайт для запуска простого сервера через командную строку с помощью python.
Я добавил несколько строк print
, потому что я хотел бы распечатать параметры GET и POST через командную строку для запросов, но я не могу заставить их отображаться где угодно.
Если я просто напечатаю нашу переменную 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>}
Я попытался использовать команду print
с каждым из индексов (pprint (vars(s.connection))
), но это не работает.
Вот модифицированный 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)
Как распечатать параметры POST и GET с помощью простого script?
Желаемый вывод через командную строку будет выглядеть примерно так:
1.0.0.127. - - [03/Oct/2012 16:02:05] "POST / HTTP/1.1" 200 -
foo=1
bar=2
bis=3
Ответы
Ответ 1
Это не очень очевидно, но обработчик использует сокеты за кулисами. Поэтому вам нужно прочитать необработанные данные из сокета, а затем интерпретировать его.
Используйте модуль urlparse
.
- В Python 2 вы хотите
urlparse.parse_qs
.
- В Python 3 библиотека переименована: вы хотите
urllib.parse.parse_qs
.
Импортируйте 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()
...
Настройте простой тестовый клиент:
#!/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
Запустите сервер, а затем запустите клиент:
[email protected]$ python http_server.py
Wed Oct 3 21:38:51 2012 Server Starts - localhost:9000
foo=[u'1']
bar=[u'2']
bis=[u'3']
Ответ 2
Вы можете использовать cgi
модуль вместо urlparse
. cgi
реализует парсинг параметров POST из коробки. Использование хорошо протестированных библиотек кажется лучше.
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)