configurationengine/source/cone/storage/tests/simplewebserver.py
author terytkon
Thu, 11 Mar 2010 17:04:37 +0200
changeset 0 2e8eeb919028
permissions -rw-r--r--
Adding EPL version of configurationengine.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     1
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     2
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     3
# All rights reserved.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     4
# This component and the accompanying materials are made available
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     5
# under the terms of "Eclipse Public License v1.0"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     6
# which accompanies this distribution, and is available
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     7
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     8
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
     9
# Initial Contributors:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    10
# Nokia Corporation - initial contribution.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    11
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    12
# Contributors:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    13
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    14
# Description:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    15
#
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    16
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    17
import SimpleHTTPServer
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    18
import SocketServer
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    19
import threading
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    20
import httplib
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    21
import os
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    22
import simplejson
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    23
import urllib
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    24
import urlparse
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    25
import posixpath
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    26
import cgi
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    27
from StringIO import StringIO
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    28
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    29
class SimpleWebHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    30
    def __init__(self, request, client_address, server):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    31
        SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    32
        self.action = ''
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    33
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    34
    def send_head(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    35
        """Common code for GET and HEAD commands.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    36
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    37
        This sends the response code and MIME headers.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    38
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    39
        Return value is either a file object (which has to be copied
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    40
        to the outputfile by the caller unless the command was HEAD,
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    41
        and must be closed by the caller under all circumstances), or
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    42
        None, in which case the caller has nothing further to do.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    43
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    44
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    45
        (action,path) = self.translate_path(self.path)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    46
        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    47
        if action == 'list_resources':
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    48
            return self.list_directory(path)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    49
        elif action == 'get_resource':
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    50
            return self.get_resource(path) 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    51
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    52
            self.send_error(404, "File not found")
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    53
            return None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    54
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    55
    def get_resource(self,path):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    56
        f = None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    57
        ctype = self.guess_type(path)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    58
        if ctype.startswith('text/'):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    59
            mode = 'r'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    60
        else:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    61
            mode = 'rb'
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    62
        try:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    63
            f = open(path, mode)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    64
        except IOError:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    65
            self.send_error(404, "File not found")
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    66
            return None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    67
        self.send_response(200)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    68
        self.send_header("Content-type", ctype)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    69
        fs = os.fstat(f.fileno())
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    70
        self.send_header("Content-Length", str(fs[6]))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    71
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    72
        self.end_headers()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    73
        return f
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    74
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    75
    def list_directory(self, path):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    76
        """Helper to produce a directory listing (absent index.html).
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    77
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    78
        Return value is either a file object, or None (indicating an
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    79
        error).  In either case, the headers are sent, making the
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    80
        interface the same as for send_head().
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    81
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    82
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    83
        try:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    84
            list = os.listdir(path)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    85
        except os.error:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    86
            self.send_error(404, "No permission to list directory")
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    87
            return None
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    88
        list.sort(key=lambda a: a.lower())
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    89
        f = StringIO()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    90
        displaypath = cgi.escape(urllib.unquote(self.path))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    91
        files = []
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    92
        for name in list:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    93
            fullname = os.path.join(path, name)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    94
            displayname = linkname = name
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    95
            # Append / for directories or @ for symbolic links
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    96
            if os.path.isdir(fullname):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    97
                displayname = name + "/"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    98
                linkname = name + "/"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
    99
            if os.path.islink(fullname):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   100
                displayname = name + "@"
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   101
                # Note: a link to a directory displays with @ and links with /
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   102
            files.append(displayname)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   103
        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   104
        f.write(simplejson.dumps(files))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   105
        length = f.tell()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   106
        f.seek(0)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   107
        self.send_response(200)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   108
        self.send_header("Content-type", "text/html")
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   109
        self.send_header("Content-Length", str(length))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   110
        self.end_headers()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   111
        return f
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   112
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   113
    def translate_path(self, path):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   114
        """Translate a /-separated PATH to the local filename syntax.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   115
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   116
        Components that mean special things to the local file system
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   117
        (e.g. drive or directory names) are ignored.  (XXX They should
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   118
        probably be diagnosed.)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   119
        @return: action,path
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   120
        """
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   121
        # abandon query parameters
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   122
        action = ''
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   123
        path = urlparse.urlparse(path)[2]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   124
        path = path.lstrip('/')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   125
        splittedpath = path.split('/')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   126
        if len(splittedpath) > 1:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   127
            action = splittedpath[1]
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   128
            path   = "/".join(splittedpath[2:])
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   129
            path = posixpath.normpath(urllib.unquote(path))
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   130
            words = path.split('/')
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   131
            words = filter(None, words)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   132
            path = os.getcwd()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   133
            for word in words:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   134
                drive, word = os.path.splitdrive(word)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   135
                head, word = os.path.split(word)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   136
                if word in (os.curdir, os.pardir): continue
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   137
                path = os.path.join(path, word)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   138
        return (action,path)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   139
        
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   140
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   141
class SimpleWebServer(threading.Thread):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   142
    def __init__(self, folder=".", port=8000):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   143
        super(SimpleWebServer,self).__init__()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   144
        self.PORT    = port
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   145
        self.folder  = folder
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   146
        self.handler = SimpleWebHandler
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   147
        self.httpd   = SocketServer.TCPServer(("localhost", self.PORT), self.handler)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   148
        self.active  = False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   149
        print "serving at port", self.PORT
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   150
 
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   151
    def run(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   152
        # minimal web server.  serves files relative to the
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   153
        # current directory.
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   154
        os.chdir(self.folder)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   155
        self.active = True
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   156
        while self.active:
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   157
            self.httpd.handle_request()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   158
        return 0
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   159
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   160
    def stop(self):
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   161
        self.active = False
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   162
        conn = httplib.HTTPConnection('localhost', self.PORT)
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   163
        conn.request("GET", "/")
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   164
        r1 = conn.getresponse()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   165
        print r1.status, r1.reason
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   166
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   167
if __name__ == '__main__':
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   168
    server = SimpleWebServer()
2e8eeb919028 Adding EPL version of configurationengine.
terytkon
parents:
diff changeset
   169
    server.start()