Cette page présente un petit exemple de CGI fait en Python.
L'exemple choisi ici est un outil de tests réseau à distance réalisé à l'occasion d'un problème de routage chez le FAI qu'il ne constatait pas depuis son propre réseau.
Cet exemple montre comment faire un CGI rapidement pour un besoin ponctuel, en Python pur sans autre dépendance (pas de Django ou autre Pylons ici).
Fichier /usr/lib/cgi-bin/network-test.py :
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 Network test tools (CGI)
5
6 Copyright ©2009 Agence universitaire de la Francophonie
7 Licence: GNU General Public License, version 2
8 Author: Progfou <jean-christophe.andre@auf.org>
9 Creation: 2009-03-21
10
11 Debian-Depends: mtr-tiny iputils-ping dnsutils
12 Filename: /usr/lib/cgi-bin/network-test.py (chmod +x)
13 Usage: http://localhost/cgi-bin/network-test.py
14 """
15
16 import os
17 import cgi
18 import commands
19
20 ACTIONS = {
21 'mtr': u"mtr -rc%(count)s %(addr)s",
22 'ping': u"ping -nc%(count)s %(addr)s",
23 'host': u"host %(addr)s",
24 'dig': u"dig any %(addr)s",
25 'dig +trace': u"dig any +trace %(addr)s",
26 'dig +nssearch': u"dig +nssearch %(addr)s",
27 'source': u"cat %(__file__)s",
28 }
29
30 COUNT = 3
31
32 HTML = u"""<html>
33 <head>
34 <title>%(title)s</title>
35 <style type="text/css">
36 body { margin: 0; padding: 0; }
37 h1 { margin: 0; padding: 2pt; background: red; color: yellow; text-align: center; font-family: sans; }
38 fieldset { margin: 5pt; padding: 5pt; background: #E0E0FF; }
39 fieldset legend { margin: 5pt; padding: 2pt; background: #E0E0FF; border: 1.5pt groove lightgrey; font-weight: bold; }
40 fieldset pre { margin: 0pt; padding: 2pt; background: white; width: 80em; border: 2pt inset lightgrey; }
41 span.error { font-weight: bold; color: red; }
42 div.signature { margin: 5pt; color: grey; text-align: right; font-size: 70%%; }
43 </style>
44 </head>
45 <body>
46 <h1>%(title)s</h1>
47 <form>
48 %(content)s
49 </form>
50 %(signature)s
51 </body>
52 </html>
53 """
54
55 TITLE = u"""Network test tools @ %(HTTP_HOST)s[%(SERVER_ADDR)s]"""
56
57 REQUEST = u"""<fieldset>
58 <legend>Request</legend>
59 <label>Hostname or IP address:</label>
60 <input name="addr" type="text" size="16" maxwidth="16" value="%(addr)s" />
61 <input name="action" type="submit" value="mtr" />
62 <input name="action" type="submit" value="ping" />
63 <input name="action" type="submit" value="host" />
64 <input name="action" type="submit" value="dig" />
65 <input name="action" type="submit" value="dig +trace" />
66 <input name="action" type="submit" value="dig +nssearch" />
67 <br />
68 <br />
69 (You'll have to wait about %(count)s seconds after clic for result to display.)
70 </fieldset>
71 """
72
73 ERROR = u"""<fieldset>
74 <legend>Error</legend>
75 <span class="error">%(content)s</span>
76 </fieldset>
77 """
78
79 RESULT = u"""<fieldset>
80 <legend>Result%(legend_ext)s</legend>
81 <pre>%(content)s</pre>
82 </fieldset>
83 """
84
85 SIGNATURE = u"""<div class="signature">
86 Copyright ©2009 Agence universitaire de la Francophonie<br />
87 <a href="http://www.auf.org/regions/asie-pacifique/">http://www.auf.org/regions/asie-pacifique/</a><br />
88 <span style="font-size: 70%%">(<a href="?action=source">view this script source</a>)</span>
89 </div>
90 """
91
92 if __name__ == "__main__":
93 query_string = cgi.parse_qs(os.environ['QUERY_STRING'])
94 addr = query_string.get('addr', ["www.auf.org"])[0]
95 count = query_string.get('count', [COUNT])[0]
96 result_legend_ext = ""
97 error = None
98 result = None
99
100 # check URL parameters
101 if not addr.replace('.','').replace('-','').isalnum():
102 error = u"Invalid address!"
103 addr = "invalid"
104 elif type(count) == str and not count.isdigit():
105 error = u"Invalid count!"
106 count = COUNT
107 else:
108 # process request
109 action = query_string.get('action', [None])[0]
110 if action in ACTIONS:
111 command = (ACTIONS[action] % locals()).encode('utf-8')
112 (status, result) = commands.getstatusoutput(command)
113 result = result.decode('utf-8', 'ignore')
114 result_legend_ext = u" for `%s`" % command
115 elif action is not None:
116 error = u"Invalid action!"
117
118 # display result
119 print u"Content-Type: text/html; charset=utf-8\n"
120 #cgi.print_environ()
121 title = TITLE % os.environ
122 content = REQUEST % locals()
123 if error is not None:
124 content += ERROR % {'content': cgi.escape(error)}
125 if result is not None:
126 content += RESULT % {'content': cgi.escape(result),
127 'legend_ext': result_legend_ext}
128 signature = SIGNATURE % locals()
129 print (HTML % locals()).encode('utf-8')
Exemple d'utilisation : http://smtp.vn.auf.org/cgi-bin/network-test.py