Как я могу отлаживать POST-запросы с помощью BaseHTTPServer / SimpleHTTPServer python?

Я нашел скрипт на этом сайте для запуска простого сервера через командную строку с помощью 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)) ), но это не работает.

Вот модифицированный скрипт:

 #!/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 с помощью простого сценария?

Желаемый вывод через командную строку будет выглядеть примерно так:

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

Это не очень очевидно, но обработчик использует сокеты за кулисами. Поэтому вам нужно прочитать необработанные данные из сокета, а затем интерпретировать его.

Используйте модуль 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'] 

Вы можете использовать модуль cgi вместо urlparse . cgi реализует параметры POST params из коробки. Использование хорошо протестированных библиотек кажется лучше.

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)