simplehttpserver.py 3.41 KB
Newer Older
1
# -*- coding: utf-8 -*-
2 3
from six.moves.SimpleHTTPServer import SimpleHTTPRequestHandler
from six.moves.BaseHTTPServer import HTTPServer
4 5 6 7 8
import ssl
import os
import logging
from netaddr import valid_ipv4, valid_ipv6
import socket
9
import cgi, errno
10

11 12 13
from slapos.util import str2bytes


14 15
class ServerHandler(SimpleHTTPRequestHandler):

16 17 18 19
  document_path = ''
  restrict_root_folder = True

  def respond(self, code=200, type='text/html'):
20 21 22 23
    self.send_response(code)
    self.send_header("Content-type", type)
    self.end_headers()

24 25
  def restrictedRootAccess(self):
    if self.restrict_root_folder and self.path and self.path == '/':
26 27
      # no access to root path
      self.respond(403)
28
      self.wfile.write(b"Forbidden")
29 30 31 32 33 34
      return True
    return False

  def do_GET(self):
    logging.info('%s - GET: %s \n%s' % (self.client_address[0], self.path, self.headers))
    if self.restrictedRootAccess():
35 36 37
      return
    SimpleHTTPRequestHandler.do_GET(self)

38 39 40 41 42 43 44 45 46 47 48 49 50 51
  def do_POST(self):
    logging.info('%s - POST: %s \n%s' % (self.client_address[0], self.path, self.headers))
    if self.restrictedRootAccess():
      return

    form = cgi.FieldStorage(
      fp=self.rfile,
      headers=self.headers,
      environ={'REQUEST_METHOD':'POST',
                'CONTENT_TYPE':self.headers['Content-Type']}
    )
    name = form['path'].value
    content = form['content'].value
    method = 'a'
52
    if 'clear' in form and form['clear'].value == '1':
53 54 55
      method = 'w'
    self.writeFile(name, content, method)
    self.respond(200, type=self.headers['Content-Type'])
56
    self.wfile.write(b"Content written to %s" % str2bytes(name))
57 58 59 60 61 62 63 64 65 66 67 68 69 70

  def writeFile(self, filename, content, method='a'):
    file_path = os.path.join(self.document_path, filename)

    try:
      os.makedirs(os.path.dirname(file_path))
    except OSError as exception:
      if exception.errno != errno.EEXIST:
        logging.error('Failed to create file in %s. The error is \n%s' % (
          file_path, str(exception)))

    logging.info('Writing recieved content to file %s' % file_path)
    try:
      with open(file_path, method) as myfile:
71
        myfile.write(content)
72 73 74 75 76
        logging.info('Done.')
    except IOError as e:
      logging.error('Something happened while processing \'writeFile\'. The message is %s' %
                    str(e))

77 78
class HTTPServerV6(HTTPServer):
  address_family = socket.AF_INET6
79

80 81 82 83 84 85 86 87 88 89 90 91 92

def run(args):
  
  # minimal web server.  serves files relative to the
  # current directory.
  logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                            filename=args['log-file'] ,level=logging.INFO)
  
  port = args['port']
  host = args['host']
  os.chdir(args['cwd'])
  
  Handler = ServerHandler
93 94
  Handler.document_path = args['root-dir']
  Handler.restrict_root_folder = (args['root-dir'] != args['cwd'])
95 96 97 98 99 100 101
  
  if valid_ipv6(host):
    server = HTTPServerV6
  else:
    server = HTTPServer
  
  httpd = server((host, port), Handler)
102
  scheme = 'http'
103
  if 'cert-file' in args and 'key-file' in args and \
104 105
      os.path.exists(args['cert-file']) and os.path.exists(args['key-file']):
    scheme = 'https'
106 107 108 109 110
    httpd.socket = ssl.wrap_socket (httpd.socket, 
                                     server_side=True,
                                     certfile=args['cert-file'],
                                     keyfile=args['key-file'])

111
  logging.info("Starting simple http server at %s://%s:%s" % (scheme, host, port))
112
  httpd.serve_forever()