1
2 import os
3 import sys
4 import shlex
5 import optparse
6 import mimetypes
7 import posixpath
8 import webbrowser
9 import subprocess
10 import BaseHTTPServer as httpserv
11
12 from starcluster import templates
13 from starcluster import exception
14 from starcluster.logger import log
15
16 ERROR_MSG = """\
17 <head>
18 <title>DOH!</title>
19 </head>
20 <body>
21 <pre>
22 _ _ ___ _ _
23 | || | / _ \| || |
24 | || |_| | | | || |_
25 |__ _| |_| |__ _|
26 |_| \___/ |_|
27
28 </pre>
29 <h1>Error response</h1>
30 <p>Error code %(code)d.
31 <p>Message: %(message)s.
32 <p>Error code explanation: %(code)s = %(explain)s.
33 </body>
34 """
35
36
38 """http server that reacts to self.stop flag"""
39
41 """Handle one request at a time until stopped."""
42 self.stop = False
43 while not self.stop:
44 self.handle_request()
45
46
48 error_message_format = ERROR_MSG
49
51 print 'GET not supported'
52
54 print 'POSTing not supported'
55
57 log.info("Shutting down server...")
58 self.send_response(200)
59 self.send_header('Content-type', 'text/html')
60 self.end_headers()
61 self.server.stop = True
62
63
65
67 try:
68 docroot = globals()['DOCUMENTROOT']
69 fname = posixpath.join(docroot, self.path[1:])
70
71 fname = fname.split('?')[0]
72 if fname.endswith('/') or os.path.isdir(fname):
73 fname = posixpath.join(fname, 'index.html')
74 f = open(fname)
75 content_type = mimetypes.guess_type(fname)[0]
76 self.send_response(200)
77 self.send_header('Content-type', content_type)
78 self.end_headers()
79 while True:
80 data = f.read(2097152)
81 if not data:
82 break
83 self.wfile.write(data)
84
85 f.close()
86 return
87 except IOError:
88 self.send_error(404, 'File Not Found: %s' % self.path)
89
90
92 """
93 Simple GET handler that loads and renders files/templates within a package
94 under the starcluster.templates package. You can set the _root_template_pkg
95 attribute on this class before passing to BaseHTTPServer to specify a
96 starcluster.templates subpackage to render templates from. Defaults to
97 rendering starcluster.templates (ie '/')
98 """
99 _root_template_pkg = '/'
100 _tmpl_context = {}
101 _bin_exts = ('.ico', '.gif', '.jpg', '.png')
102
104 relpath = self.path[1:].split('?')[0]
105 if relpath == "shutdown":
106 self.do_shutdown()
107 return
108 fullpath = posixpath.join(self._root_template_pkg, relpath)
109 try:
110 if relpath.endswith(self._bin_exts):
111 data = templates.get_resource(fullpath).read()
112 else:
113 tmpl = templates.get_template(fullpath)
114 data = tmpl.render(**self._tmpl_context)
115 content_type = mimetypes.guess_type(os.path.basename(relpath))[0]
116 self.send_response(200)
117 self.send_header('Content-type', content_type)
118 self.end_headers()
119 self.wfile.write(data)
120 except IOError, templates.TemplateNotFound:
121 self.send_error(404, 'File Not Found: %s' % self.path)
122 return
123
124
125 -def get_template_server(root_template_pkg='/', interface="localhost",
126 port=None, context={}):
132
133
135 if port is None:
136 port = 0
137 server = StoppableHttpServer((interface, port), handler)
138 return server
139
140
142 """Class for all browsers which are to be started in the background."""
143 - def open(self, url, new=0, autoraise=1):
144 cmdline = [self.name] + [arg.replace("%s", url)
145 for arg in self.args]
146 try:
147 if sys.platform[:3] == 'win':
148 p = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
149 else:
150 setsid = getattr(os, 'setsid', None)
151 if not setsid:
152 setsid = getattr(os, 'setpgrp', None)
153 p = subprocess.Popen(cmdline, close_fds=True,
154 preexec_fn=setsid, stdout=subprocess.PIPE)
155 return (p.poll() is None)
156 except OSError:
157 return False
158
159
161 return os.path.exists(fpath) and os.access(fpath, os.X_OK)
162
163
165 fpath, fname = os.path.split(program)
166 if fpath:
167 if _is_exe(program):
168 return program
169 else:
170 for path in os.environ["PATH"].split(os.pathsep):
171 exe_file = os.path.join(path, program)
172 if _is_exe(exe_file):
173 return exe_file
174
175
177 if browser_cmd:
178 cmd = shlex.split(browser_cmd)
179 arg0 = cmd[0]
180 if not _which(arg0):
181 raise exception.BaseException("browser %s does not exist" % arg0)
182 if "%s" not in browser_cmd:
183 cmd.append("%s")
184 browser = BackgroundBrowser(cmd)
185 else:
186
187 browser = webbrowser.get()
188 log.info("Browsing %s using '%s'..." % (url, browser.name))
189 return browser.open(url)
190
191
192 -def main(path, interface="localhost", port=8080):
193 try:
194 docroot = os.path.realpath(path)
195 globals()['DOCUMENTROOT'] = docroot
196 server = get_webserver(interface=interface, port=port,
197 handler=DocrootHandler)
198 log.info('Starting httpserver...')
199 log.info('Document_root = %s' % docroot)
200 server.serve_forever()
201 except KeyboardInterrupt:
202 print '^C received, shutting down server'
203 server.socket.close()
204
205
206 if __name__ == '__main__':
207 parser = optparse.OptionParser()
208 parser.add_option("-i", "--interface", dest="interface", action="store",
209 default="localhost")
210 parser.add_option("-p", "--port", dest="port", action="store", type="int",
211 default=8080)
212 opts, args = parser.parse_args()
213 if len(args) != 1:
214 parser.error('usage: webserver.py <document_root>')
215 path = args[0]
216 main(path, **opts.__dict__)
217