Processing HTTP GET input parameter on server side in python
Question:
I wrote a simple HTTP client and server in Python for experimenting. The first code snippet below shows how I send an HTTP GET request with a parameter named imsi. In the second code snippet I show my do_Get function implementation in the server side. My question is how I can extract the imsi parameter in the server code and send a response back to the client in order to signal the client that imsi is valid.
Thanks.
P.S.: I verified that the client sends the request successfully.
CLIENT code snippet
params = urllib.urlencode({'imsi': str(imsi)})
conn = httplib.HTTPConnection(host + ':' + str(port))
#conn.set_debuglevel(1)
conn.request("GET", "/index.htm", 'imsi=' + str(imsi))
r = conn.getresponse()
SERVER code snippet
import sys, string, cStringIO, cgi, time, datetime
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
# I want to extract the imsi parameter here and send a success response to
# back to the client.
def do_GET(self):
try:
if self.path.endswith(".html"):
#self.path has /index.htm
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write("<h1>Device Static Content</h1>")
self.wfile.write(f.read())
f.close()
return
if self.path.endswith(".esp"): #our dynamic content
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write("<h1>Dynamic Dynamic Content</h1>")
self.wfile.write("Today is the " + str(time.localtime()[7]))
self.wfile.write(" day in the year " + str(time.localtime()[0]))
return
# The root
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
lst = list(sys.argv[1])
n = lst[len(lst) - 1]
now = datetime.datetime.now()
output = cStringIO.StringIO()
output.write("<html><head>")
output.write("<style type="text/css">")
output.write("h1 {color:blue;}")
output.write("h2 {color:red;}")
output.write("</style>")
output.write("<h1>Device #" + n + " Root Content</h1>")
output.write("<h2>Device Addr: " + sys.argv[1] + ":" + sys.argv[2] + "</h1>")
output.write("<h2>Device Time: " + now.strftime("%Y-%m-%d %H:%M:%S") + "</h2>")
output.write("</body>")
output.write("</html>")
self.wfile.write(output.getvalue())
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
Answers:
You can parse the query of a GET request using urlparse, then split the query string.
from urlparse import urlparse
query = urlparse(self.path).query
query_components = dict(qc.split("=") for qc in query.split("&"))
imsi = query_components["imsi"]
# query_components = { "imsi" : "Hello" }
# Or use the parse_qs method
from urlparse import urlparse, parse_qs
query_components = parse_qs(urlparse(self.path).query)
imsi = query_components["imsi"]
# query_components = { "imsi" : ["Hello"] }
You can confirm this by using
curl http://your.host/?imsi=Hello
BaseHTTPServer is a pretty low-level server. Generally you want to use a real web framework that does this kind of grunt work for you, but since you asked…
First import a url parsing library. In Python 2,x it’s urlparse. (In Python3, you’d use urllib.parse)
import urlparse
Then, in your do_get method, parse the query string.
imsi = urlparse.parse_qs(urlparse.urlparse(self.path).query).get('imsi', None)
print imsi # Prints None or the string value of imsi
Also, you could be using urllib in your client code and it would probably be a lot easier.
cgi
module contains FieldStorage
class which is supposed to be used in CGI context, but seems to be easily used in your context as well.
If you dont want to import additional libraries in most cases you can use:
i = self.path.index ( "?" ) + 1
params = dict ( [ tuple ( p.split("=") ) for p in self.path[i:].split ( "&" ) ] )
I wrote a simple HTTP client and server in Python for experimenting. The first code snippet below shows how I send an HTTP GET request with a parameter named imsi. In the second code snippet I show my do_Get function implementation in the server side. My question is how I can extract the imsi parameter in the server code and send a response back to the client in order to signal the client that imsi is valid.
Thanks.
P.S.: I verified that the client sends the request successfully.
CLIENT code snippet
params = urllib.urlencode({'imsi': str(imsi)})
conn = httplib.HTTPConnection(host + ':' + str(port))
#conn.set_debuglevel(1)
conn.request("GET", "/index.htm", 'imsi=' + str(imsi))
r = conn.getresponse()
SERVER code snippet
import sys, string, cStringIO, cgi, time, datetime
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
# I want to extract the imsi parameter here and send a success response to
# back to the client.
def do_GET(self):
try:
if self.path.endswith(".html"):
#self.path has /index.htm
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write("<h1>Device Static Content</h1>")
self.wfile.write(f.read())
f.close()
return
if self.path.endswith(".esp"): #our dynamic content
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write("<h1>Dynamic Dynamic Content</h1>")
self.wfile.write("Today is the " + str(time.localtime()[7]))
self.wfile.write(" day in the year " + str(time.localtime()[0]))
return
# The root
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
lst = list(sys.argv[1])
n = lst[len(lst) - 1]
now = datetime.datetime.now()
output = cStringIO.StringIO()
output.write("<html><head>")
output.write("<style type="text/css">")
output.write("h1 {color:blue;}")
output.write("h2 {color:red;}")
output.write("</style>")
output.write("<h1>Device #" + n + " Root Content</h1>")
output.write("<h2>Device Addr: " + sys.argv[1] + ":" + sys.argv[2] + "</h1>")
output.write("<h2>Device Time: " + now.strftime("%Y-%m-%d %H:%M:%S") + "</h2>")
output.write("</body>")
output.write("</html>")
self.wfile.write(output.getvalue())
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
You can parse the query of a GET request using urlparse, then split the query string.
from urlparse import urlparse
query = urlparse(self.path).query
query_components = dict(qc.split("=") for qc in query.split("&"))
imsi = query_components["imsi"]
# query_components = { "imsi" : "Hello" }
# Or use the parse_qs method
from urlparse import urlparse, parse_qs
query_components = parse_qs(urlparse(self.path).query)
imsi = query_components["imsi"]
# query_components = { "imsi" : ["Hello"] }
You can confirm this by using
curl http://your.host/?imsi=Hello
BaseHTTPServer is a pretty low-level server. Generally you want to use a real web framework that does this kind of grunt work for you, but since you asked…
First import a url parsing library. In Python 2,x it’s urlparse. (In Python3, you’d use urllib.parse)
import urlparse
Then, in your do_get method, parse the query string.
imsi = urlparse.parse_qs(urlparse.urlparse(self.path).query).get('imsi', None)
print imsi # Prints None or the string value of imsi
Also, you could be using urllib in your client code and it would probably be a lot easier.
cgi
module contains FieldStorage
class which is supposed to be used in CGI context, but seems to be easily used in your context as well.
If you dont want to import additional libraries in most cases you can use:
i = self.path.index ( "?" ) + 1
params = dict ( [ tuple ( p.split("=") ) for p in self.path[i:].split ( "&" ) ] )