Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python2.7
- # -*- coding: utf-8 -*-
- import argparse
- import HTTPRequestHandler
- import BaseHTTPServer
- import logging
- import os
- import sys
- def make_request_handler_class(opts):
- MyHTTPRequestHandler = HTTPRequestHandler
- MyHTTPRequestHandler.m_opts = opts
- return MyHTTPRequestHandler
- def make_http_handler_class(opts, localHTTPRequestHandler):
- '''
- Factory to make the request handler and add arguments to it.
- It exists to allow the handler to access the opts.path variable
- locally.
- '''
- class MyHTTPHandlerClass(BaseHTTPServer.BaseHTTPRequestHandler):
- m_opts = opts
- m_HTTPRequestHandler = localHTTPRequestHandler
- def do_HEAD(self):
- '''
- Handle a HEAD request.
- '''
- logging.debug('HEADER %s' % (self.path))
- self.send_response(200)
- self.send_header('Content-type', 'text/html')
- self.end_headers()
- def do_GET(self):
- MyHTTPHandlerClass.m_HTTPRequestHandler.do_GET(self)
- return MyHTTPHandlerClass
- def err(msg):
- '''
- Report an error message and exit.
- '''
- print('ERROR: %s' % (msg))
- sys.exit(1)
- def getopts():
- '''
- Get the command line options.
- '''
- # Get the help from the module documentation.
- this = os.path.basename(sys.argv[0])
- description = ('description:%s' % '\n '.join(__doc__.split('\n')))
- epilog = ' '
- rawd = argparse.RawDescriptionHelpFormatter
- parser = argparse.ArgumentParser(formatter_class=rawd,
- description=description,
- epilog=epilog)
- parser.add_argument('-d', '--daemonize',
- action='store',
- type=str,
- default='.',
- metavar='DIR',
- help='daemonize this process, store the 3 run files (.log, .err, .pid) in DIR (default "%(default)s")')
- parser.add_argument('-H', '--host',
- action='store',
- type=str,
- default='localhost',
- help='hostname, default=%(default)s')
- parser.add_argument('-l', '--level',
- action='store',
- type=str,
- default='info',
- choices=['notset', 'debug', 'info', 'warning', 'error', 'critical',],
- help='define the logging level, the default is %(default)s')
- parser.add_argument('--no-dirlist',
- action='store_true',
- help='disable directory listings')
- parser.add_argument('-p', '--port',
- action='store',
- type=int,
- default=8080,
- help='port, default=%(default)s')
- parser.add_argument('-r', '--rootdir',
- action='store',
- type=str,
- default=os.path.abspath('.'),
- help='web directory root that contains the HTML/CSS/JS files %(default)s')
- parser.add_argument('-v', '--verbose',
- action='count',
- help='level of verbosity')
- parser.add_argument('-V', '--version',
- action='version',
- version='%(prog)s - v' + VERSION)
- opts = parser.parse_args()
- opts.rootdir = os.path.abspath(opts.rootdir)
- if not os.path.isdir(opts.rootdir):
- err('Root directory does not exist: ' + opts.rootdir)
- if opts.port < 1 or opts.port > 65535:
- err('Port is out of range [1..65535]: %d' % (opts.port))
- return opts
- def httpd(opts):
- '''
- HTTP server
- '''
- RequestHandlerClass = make_request_handler_class(opts)
- HTTPHandlerClass = make_http_handler_class(opts, RequestHandlerClass)
- server = BaseHTTPServer.HTTPServer((opts.host, opts.port), HTTPHandlerClass)
- logging.info('Server starting %s:%s (level=%s)' % (opts.host, opts.port, opts.level))
- try:
- server.serve_forever()
- except KeyboardInterrupt:
- pass
- server.server_close()
- logging.info('Server stopping %s:%s' % (opts.host, opts.port))
- def get_logging_level(opts):
- '''
- Get the logging levels specified on the command line.
- The level can only be set once.
- '''
- if opts.level == 'notset':
- return logging.NOTSET
- elif opts.level == 'debug':
- return logging.DEBUG
- elif opts.level == 'info':
- return logging.INFO
- elif opts.level == 'warning':
- return logging.WARNING
- elif opts.level == 'error':
- return logging.ERROR
- elif opts.level == 'critical':
- return logging.CRITICAL
- def daemonize(opts):
- '''
- Daemonize this process.
- CITATION: http://stackoverflow.com/questions/115974/what-would-be-the-simplest-way-to-daemonize-a-python-script-in-linux
- '''
- if os.path.exists(opts.daemonize) is False:
- err('directory does not exist: ' + opts.daemonize)
- if os.path.isdir(opts.daemonize) is False:
- err('not a directory: ' + opts.daemonize)
- bname = 'webserver-%s-%d' % (opts.host, opts.port)
- outfile = os.path.abspath(os.path.join(opts.daemonize, bname + '.log'))
- errfile = os.path.abspath(os.path.join(opts.daemonize, bname + '.err'))
- pidfile = os.path.abspath(os.path.join(opts.daemonize, bname + '.pid'))
- if os.path.exists(pidfile):
- err('pid file exists, cannot continue: ' + pidfile)
- if os.path.exists(outfile):
- os.unlink(outfile)
- if os.path.exists(errfile):
- os.unlink(errfile)
- if os.fork():
- sys.exit(0) # exit the parent
- os.umask(0)
- os.setsid()
- if os.fork():
- sys.exit(0) # exit the parent
- print('daemon pid %d' % (os.getpid()))
- sys.stdout.flush()
- sys.stderr.flush()
- stdin = file('/dev/null', 'r')
- stdout = file(outfile, 'a+')
- stderr = file(errfile, 'a+', 0)
- os.dup2(stdin.fileno(), sys.stdin.fileno())
- os.dup2(stdout.fileno(), sys.stdout.fileno())
- os.dup2(stderr.fileno(), sys.stderr.fileno())
- with open(pidfile, 'w') as ofp:
- ofp.write('%i' % (os.getpid()))
- def main():
- ''' main entry '''
- opts = getopts()
- if opts.daemonize:
- daemonize(opts)
- logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s', level=get_logging_level(opts))
- httpd(opts)
- if __name__ == '__main__':
- main() # this allows library functionality
Add Comment
Please, Sign In to add comment