Welcome, guest | Sign In | My Account | Store | Cart

A demonstration of how the Python HTTP server classes can be used.

Python, 84 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Copyright (C) 2002, Thinkware AB, Sweden. 
 
import BaseHTTPServer 
from StringIO import StringIO 
import shutil, os 
 
class MyHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): 
 
    cmds = {'/ping': 'ping www.thinkware.se', 
            '/netstat' : 'netstat -a', 
            '/tracert': 'tracert www.thinkware.se', 
            '/srvstats': 'net statistics server', 
            '/wsstats': 'net statistics workstation', 
            '/route' : 'route print', 
            } 
 
    def do_GET(self): 
        """Serve a GET request.""" 
        f = self.send_head() 
        if f: 
            f = StringIO() 
            machine = os.popen('hostname').readlines()[0] 
            if self.path == '/': 
                heading = "Select a command to run on %s" % (machine) 
                body = (self.getMenu() + 
                        "<p>The screen won't update until the selected " 
                        "command has finished. Please be patient.") 
            else: 
                heading = "Execution of ``%s´´ on %s" % (
                           self.cmds[self.path], machine) 
                cmd = self.cmds[self.path] 
                body = '<a href="/">Main Menu</a><pre>%s</pre>\n' % os.popen( 
                    cmd).read() 
                # Translation CP437 -> Latin 1 needed for Swedish Windows. 
                body = body.decode('cp437').encode('latin1') 
            f.write("<html><head><title>%s</title></head>\n" % (heading)) 
            f.write('<body><H1>%s</H1>\n' % (heading)) 
            f.write(body) 
            f.write('</body></html>\n') 
            f.seek(0) 
            self.copyfile(f, self.wfile) 
            f.close() 
        return f 
 
    def do_HEAD(self): 
        """Serve a HEAD request.""" 
        f = self.send_head() 
        if f: 
            f.close() 
 
    def send_head(self): 
        path = self.path 
        if not path in ['/'] + self.cmds.keys(): 
            head = 'Command "%s" not found. Try one of these:<ul>' % path 
            msg = head + self.getMenu() 
            self.send_error(404, msg) 
            return None 
        self.send_response(200) 
        self.send_header("Content-type", 'text/html') 
        self.end_headers() 
        f = StringIO() 
        f.write("A test %s\n" % self.path) 
        f.seek(0) 
        return f 
 
    def getMenu(self): 
            keys = self.cmds.keys() 
            keys.sort() 
            msg = [] 
            for k in keys: 
                msg.append('<li><a href="%s">%s => %s</a></li>' %(
                                         k,  k,    self.cmds[k])) 
            msg.append('</ul>') 
            return "\n".join(msg) 
 
    def copyfile(self, source, outputfile): 
        shutil.copyfileobj(source, outputfile) 
 
def main(HandlerClass = MyHTTPRequestHandler, 
         ServerClass = BaseHTTPServer.HTTPServer): 
    BaseHTTPServer.test(HandlerClass, ServerClass) 
 
if __name__ == '__main__': 
    main() 

It's really so easy to set up a custom web server on an internal network for some simple purpose, such as network monitoring. This isn't intended to be a useful "real" program, but rather something to copy and modify.

In the example above, all substance is performed by os.popen calls, but naturally, it's very reasonable to have real work done by Python code in the same process as the web server.

1 comment

tuco Leone 20 years, 3 months ago  # | flag

Correction.

This is a nice script. It gave me all kinds of ideas.  But in
member send_head(), you should have:



self.send_header("Content-type", 'text/html') in lieu of 'text/plain'
because in a W3C complient browser (!= IE), that's what you'll get:
plain text (html tags and all).



Also, the "h/head" tag in the first f.write() should be "/head"



And please don't forget the shabang (#!/usr/bin/env python). I know
you Win32 folks don't need it but Python is a multiplatform language
and If your code is portable, use it.  After all, if Bill-boy knew you
were using Python on *his* operating system instead of his baby (VB),
he would come take your End User License Agreement away.