¿Cómo puedo depurar las solicitudes POST con BaseHTTPServer / SimpleHTTPServer de python?

Encontré un script en este sitio para ejecutar un servidor simple a través de la línea de comandos con python.

Agregué algunas líneas de print porque me gustaría imprimir los parámetros GET y POST a través de la línea de comandos para las solicitudes, pero parece que no puedo hacer que aparezcan en ninguna parte.

Si acabo de imprimir nuestra nuestra variable s ( pprint (vars(s)) ) termino viendo esto:

 {'client_address': ('127.0.0.1', 53373), 'close_connection': 1, 'command': 'GET', 'connection': , 'headers': , 'path': '/favicon.ico', 'raw_requestline': 'GET /favicon.ico HTTP/1.1\r\n', 'request': , 'request_version': 'HTTP/1.1', 'requestline': 'GET /favicon.ico HTTP/1.1', 'rfile': , 'server': , 'wfile': } 

Intenté usar el comando de print con cada uno de los índices, ( pprint (vars(s.connection)) ) pero eso no funciona.

Aquí está el script modificado:

 #!/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("Title goes here.") s.wfile.write("

This is a test.

") # If someone went to "http://something.somewhere.net/foo/bar/", # then s.path equals "/foo/bar/". s.wfile.write("

GET: You accessed path: %s

" % s.path) s.wfile.write("") 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("Title goes here.") s.wfile.write("

This is a test.

") s.wfile.write("

This is a test.

") # If someone went to "http://something.somewhere.net/foo/bar/", # then s.path equals "/foo/bar/". s.wfile.write("

POST: You accessed path: %s

" % s.path) s.wfile.write("") 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)

¿Cómo puedo imprimir los parámetros POST y GET utilizando un script simple?

La salida deseada a través de la línea de comando se vería algo así como:

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

No es tremendamente obvio, pero el manejador está usando sockets detrás de escena. Por lo tanto, debe leer los datos sin procesar del socket y luego interpretarlos.

Usa el módulo urlparse .

  • En Python 2, quieres urlparse.parse_qs .
  • En Python 3, se cambia el nombre de la biblioteca: desea urllib.parse.parse_qs .

Importe urlparse , y luego modifique su método do_POST así:

 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() ... 

Configurar un cliente de prueba simple:

 #!/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 

Inicie el servidor, y luego ejecute el cliente:

 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'] 

Puedes usar el módulo cgi lugar de urlparse . cgi implementa los parámetros POST de análisis fuera de la caja. Usar bibliotecas bien probadas parece mejor.

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)