non-file-based web server?
tgfuchs at my-deja.com
tgfuchs at my-deja.com
Fri Oct 15 06:06:17 EDT 1999
In article <87hfjuwngo.fsf at ethereal.dhis.org>,
Nolan Darilek <nolan at ethereal.dhis.org> wrote:
> Wow, nice technical terminology in the subject line, no? :)
>
> Out of curiousity, is there an HTTP server written in Python which
> doesn't depend on files? Instead, what I'd like to do is to use
> HTMLgen to generate dynamic content within the program, and serve
> that via the web server.
>
> My goal, in a nutshell, is to implement a simple package installer
> which uses a web interface. Basically, the installer launches a web
> server and either gives the user the URL to connect to, or launches a
> specific web browser to view the page and start the
> installation. Though I'm sure I could provide HTML with the package,
> it'd be great if the pages could all originate within the install
> script.
>
It is easy to write your own http server derived from BaseHTTPServer.py.
This is my preferred method for a simple GUI.
See the following code as an example.
"""
simple http server
it executes a system command and returns stdout or return code of command
as plain text
arguments: -port portnumber
default port: 8000
accepted urls:
/command?cmd=command # perform command
/command/form/get # send form for get
/command/form/post # send form for post
This server is intended to be a starting point for writing any simple http
server. Modify the part between -- edit begin -- and -- edit end -- supported
methods are GET, HEAD and POST, where POST content-type must be
application/x-www-form-urlencoded Two functions must be provided:
analyse(pathlist, d, headOnly = None) pathlist is the path part as list
splitted by '/' d is the query string as dictionary headOnly is set, if
method is HEAD the function must return value a triple: typ content-type,
if not set, the http return code is 404 size optional info forwarded to
do function do(info, fout) info is the result of analyse fout the output
stream the function must write the content to fout
"""
import os
import sys
import string
import SocketServer
import BaseHTTPServer
import urllib
import socket
class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
info = self.send_head()
do(info, self.wfile)
def do_HEAD(self):
self.send_head(headOnly = 1)
def do_POST(self):
ctyp = self.headers.getheader('content-type')
if ctyp != 'application/x-www-form-urlencoded':
print 'POST ERROR: unexpected content-tpye:', ctyp
return
clen = self.headers.getheader('content-length')
if clen:
clen = string.atoi(clen)
else:
print 'POST ERROR: missing content-length'
return
data = self.rfile.read(clen)
dummy = self.rfile.read(2)
self.path = '%s?%s' % (self.path, data)
self.do_GET()
def send_head(self, headOnly = None):
pathlist, d = urlParse(self.path)
typ, size, info = analyse(pathlist, d, headOnly)
if typ:
self.send_response(200) # http return code: ok
self.send_header('Content-type', typ)
if size:
self.send_header('Content-length', size)
else:
self.send_response(404) # http return code: not found
self.end_headers()
return info
# url handling
def urlParse(url):
""" return path as list and query string as dictionary
strip / from path
ignore empty values in query string
for example:
if url is: /xyz?a1=&a2=0%3A1
then result is: (['xyz'], { 'a2' : '0:1' } )
if url is: /a/b/c/
then result is: (['a', 'b', 'c'], None )
if url is: /?
then result is: ([], {} )
"""
x = string.split(url, '?')
pathlist = filter(None, string.split(x[0], '/'))
d = {}
if len(x) > 1:
q = x[-1] # eval query string
x = string.split(q, '&')
for kv in x:
y = string.split(kv, '=')
k = y[0]
try:
v = urllib.unquote_plus(y[1])
if v: # ignore empty values
d[k] = v
except:
pass
return (pathlist, d)
# -------------- edit begin ----------------------------
defaultPort = 8000 # set default port for server
def analyse(pathlist, d, headOnly = None):
size = None
info = ''
typ = None
#print pathlist, d # test only
if pathlist == ['command'] and d.keys() == ['cmd']:
typ = 'text/plain'
if not headOnly:
info = syscmd(d['cmd'])
size = len(info)
elif pathlist[:2] == ['command', 'form'] and d == {} and \
pathlist[2:] in [['get'], ['post']]:
typ = 'text/html'
if not headOnly:
info = buildform(pathlist[2])
size = len(info)
return (typ, size, info)
def do(info, fout):
fout.write(info)
# task specific helper functions
def syscmd(cmd):
f = os.popen(cmd, 'rb')
rsp = f.read()
rc = f.close()
return rsp or 'RC: %s' % rc
def buildform(method):
# get hostname of server
try:
host = socket.gethostname()
except:
host = "???"
doc = '''\
<TITLE>command %(host)s</TITLE>
<H1>command %(host)s</H1>
<P>
<FORM ACTION="/command" METHOD="%(method)s">
command: <INPUT TYPE=TEXT NAME="cmd" SIZE=80>
<BR>
<INPUT TYPE=SUBMIT>
</FORM>
''' % locals()
return doc
# -------------- edit end ----------------------------
if __name__ == '__main__':
# argument handling
try:
i = sys.argv.index('-port')
port = string.atoi(sys.argv[i+1])
del sys.argv[i:i+1]
except:
port = defaultPort
# start server
print 'Serving on port', port
server = SocketServer.TCPServer(('', port), RequestHandler)
server.serve_forever()
Sent via Deja.com http://www.deja.com/
Before you buy.
More information about the Python-list
mailing list