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