2012-10-03 14 views
14

Ho trovato uno script su this site per l'esecuzione di un semplice server tramite la riga di comando con python.Come posso eseguire il debug delle richieste POST con BaseHTTPServer/SimpleHTTPServer di python?

Ho aggiunto alcune righe print perché mi piacerebbe stampare i parametri GET e POST tramite la riga di comando per le richieste, ma non riesco a farle apparire ovunque.

Se ho appena stampare il nostro il nostro il s variabili (pprint (vars(s))) io alla fine vedere questo:

{'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>} 

Ho cercato quindi utilizzare al comando print con ciascuno degli indici, (pprint (vars(s.connection))), ma che non funziona .

Ecco lo script modificato:

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

Come posso stampare POST e GET parametri utilizzando un semplice script?

uscita desiderato tramite la riga di comando sarebbe simile:

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

risposta

23

Non è tremendamente ovvio, ma il gestore è utilizzando le prese dietro le quinte. Quindi è necessario leggere i dati grezzi dal socket e quindi interpretarli.

Utilizzare il modulo urlparse.

  • In Python 2, si desidera urlparse.parse_qs.
  • In Python 3, la libreria viene rinominata: si desidera urllib.parse.parse_qs.

Importa urlparse, e quindi modificare il vostro do_POST metodo in questo modo:

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

impostare un semplice client di prova:

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

Avviare il server e quindi eseguire il client:

[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'] 
+0

Questo avrebbe dovuto essere '' non baz' bis' :) –

+0

@Piotr Dobrogost - Proprio seguendo l'esempio del PO - portarlo con lui! :) –

5

Tu possibile utilizzare il modulo cgi anziché urlparse. cgi implementa i parametri POST parsing out of the box. L'uso di librerie ben testate sembra migliore.

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) 
Problemi correlati