I wrote most of the following script, useful for retrieving pages from the web and serving web pages. Since it is so low level, it is much more customizable than simpleHTTPserver, cgiHTTPserver, urllib, or urllib2 for advanced users. For example, you can easily set your own headers when retrieving and serving pages, such as the User-Agent header which you cannot set in either urllib or urllib2.
(sorry for not putting in any comments!) By the way, I just threw this together quickly, and haven't really had time to test retrieve() very much. Please let me know if it is buggy. I guess I should also write a dictToQuery() function. Oh well. import socket
host,port='',80 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) sock.bind((host,port)) sock.listen(1) def serve(function=lambda *args:(args[2],200,'OK',{},'')): """\ def serve(function(method,filename,httpversion,headers,get,post)) Serves one request, calling function() with the above parameters. function() must return (httpversion,code, accepted,headers,content) in that order. If you don't pass a function, then function=lambda *args:(args[2],200,'OK',{},'') """ csock,caddr=sock.accept() rfile=csock.makefile('r',0) wfile=csock.makefile('w',0) # Protocol exchange - read request headers={} line=rfile.readline().strip() split1=line.find(' ') method,remainder=line[:split1].strip(),line[split1+1:].strip() split2=remainder.find(' ') filename,httpversion=remainder[:split2].strip(),remainder[split2+1:].strip() while 1: line=rfile.readline().strip() print line if line=='': break else: split=line.find(':') key,value=line[:split],line[split+1:] headers[key.strip()]=value.strip() try: post=rfile.read(int(headers['Content-Length'])) except: post='' get=queryToDict(filename) post=queryToDict(post) loc=filename.find("?") if loc>-1: filename=filename[:loc] print "get:",`get` print "post:",`post` httpversion,code,accepted,headers,content=function(method,filename,httpversion,headers,get,post) wfile.write("%s %s %s\n"%(httpversion,code,accepted)) for header in list(headers): wfile.write("%s: %s\n"%(header,headers[header])) wfile.write("\n%s\n"%content) wfile.close() csock.close() def retrieve(host,port=80,method='GET',filename='/',httpversion='HTTP/1.0',headers={},post=''): """\ Retrieves one web page from: http://host:port/filename with the headers """ sock.connect((host,port)) rfile=sock.makefile('r',0) wfile=sock.makefile('w',0) wfile.write("%s %s %s\n"%(method,filename,httpversion)) for header in list(headers): wfile.write("%s: %s\n"%(header,headers[header])) wfile.write('\n') wfile.write("%s\n"%post) headers={} line=rfile.readline().strip() split1=line.find(' ') httpversion,remainder=line[:split1].strip(),line[split1+1:].strip() split2=remainder.find(' ') code,accepted=remainder[:split2].strip(),remainder[split2+1:].strip() while 1: line=rfile.readline().strip() if line=='': break else: split=line.find(':') key,value=line[:split],line[split+1:] headers[key.strip()]=value.strip() return httpversion,code,accepted,headers,rfile def queryToDict(query): if '?' in query: query=query[query.index('?')+1:] kvpairs=query.split("&") ret={} for kvpair in kvpairs: if '=' in kvpair: loc=kvpair.index('=') key,value=kvpair[:loc],kvpair[loc+1:] ret[key]=value return ret if __name__=='__main__': i=0 while True: i+=1 print "\nserve #%d:"%i serve(lambda *args:(args[2],200,'OK',{'Content-Type':'text/html'},'<h1>Go Away!</h1>'))
-- http://mail.python.org/mailman/listinfo/python-list