示例#1
0
 def __init__(self, server_address, xmpp_port, request_handler_class):
     testserver_base.StoppableHTTPServer.__init__(self, server_address,
                                                  request_handler_class)
     self._sync_handler = chromiumsync.TestServer()
     self._xmpp_socket_map = {}
     self._xmpp_server = xmppserver.XmppServer(self._xmpp_socket_map,
                                               ('localhost', xmpp_port))
     self.xmpp_port = self._xmpp_server.getsockname()[1]
     self.authenticated = True
示例#2
0
 def testCheckRaiseTransientError(self):
     testserver = chromiumsync.TestServer()
     http_code, raw_respon = testserver.HandleSetTransientError()
     self.assertEqual(http_code, 200)
     try:
         testserver.CheckTransientError()
         self.fail('Should have raised transient error exception')
     except chromiumsync.TransientError:
         self.assertTrue(testserver.transient_error)
示例#3
0
class TestPageHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def __init__(self, request, client_address, socket_server):
        self._connect_handlers = [
            self.RedirectConnectHandler, self.ServerAuthConnectHandler,
            self.DefaultConnectResponseHandler
        ]
        self._get_handlers = [
            self.KillHandler, self.NoCacheMaxAgeTimeHandler,
            self.NoCacheTimeHandler, self.CacheTimeHandler,
            self.CacheExpiresHandler, self.CacheProxyRevalidateHandler,
            self.CachePrivateHandler, self.CachePublicHandler,
            self.CacheSMaxAgeHandler, self.CacheMustRevalidateHandler,
            self.CacheMustRevalidateMaxAgeHandler, self.CacheNoStoreHandler,
            self.CacheNoStoreMaxAgeHandler, self.CacheNoTransformHandler,
            self.DownloadHandler, self.DownloadFinishHandler, self.EchoHeader,
            self.EchoHeaderOverride, self.EchoAllHandler, self.FileHandler,
            self.RealFileWithCommonHeaderHandler,
            self.RealBZ2FileWithCommonHeaderHandler, self.SetCookieHandler,
            self.AuthBasicHandler, self.AuthDigestHandler,
            self.SlowServerHandler, self.ContentTypeHandler,
            self.ServerRedirectHandler, self.ClientRedirectHandler,
            self.ChromiumSyncTimeHandler, self.MultipartHandler,
            self.DefaultResponseHandler
        ]
        self._post_handlers = [
            self.WriteFile, self.EchoTitleHandler, self.EchoAllHandler,
            self.ChromiumSyncCommandHandler, self.EchoHandler
        ] + self._get_handlers
        self._put_handlers = [
            self.WriteFile, self.EchoTitleHandler, self.EchoAllHandler,
            self.EchoHandler
        ] + self._get_handlers

        self._mime_types = {
            'gif': 'image/gif',
            'jpeg': 'image/jpeg',
            'jpg': 'image/jpeg',
            'xml': 'text/xml'
        }
        self._default_mime_type = 'text/html'

        BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request,
                                                       client_address,
                                                       socket_server)

    # Class variable; shared across requests.
    _sync_handler = chromiumsync.TestServer()

    def _ShouldHandleRequest(self, handler_name):
        """Determines if the path can be handled by the handler.

    We consider a handler valid if the path begins with the
    handler name. It can optionally be followed by "?*", "/*".
    """

        pattern = re.compile('%s($|\?|/).*' % handler_name)
        return pattern.match(self.path)

    def GetMIMETypeFromName(self, file_name):
        """Returns the mime type for the specified file_name. So far it only looks
    at the file extension."""

        (shortname, extension) = os.path.splitext(file_name)
        if len(extension) == 0:
            # no extension.
            return self._default_mime_type

        # extension starts with a dot, so we need to remove it
        return self._mime_types.get(extension[1:], self._default_mime_type)

    def KillHandler(self):
        """This request handler kills the server, for use when we're done"
    with the a particular test."""

        if (self.path.find("kill") < 0):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=0')
        self.end_headers()
        if options.never_die:
            self.wfile.write('I cannot die!! BWAHAHA')
        else:
            self.wfile.write('Goodbye cruel world!')
            self.server.stop = True

        return True

    def NoCacheMaxAgeTimeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and no caching requested."""

        if not self._ShouldHandleRequest("/nocachetime/maxage"):
            return False

        self.send_response(200)
        self.send_header('Cache-Control', 'max-age=0')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def NoCacheTimeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and no caching requested."""

        if not self._ShouldHandleRequest("/nocachetime"):
            return False

        self.send_response(200)
        self.send_header('Cache-Control', 'no-cache')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheTimeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and allows caching for one minute."""

        if not self._ShouldHandleRequest("/cachetime"):
            return False

        self.send_response(200)
        self.send_header('Cache-Control', 'max-age=60')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheExpiresHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and set the page to expire on 1 Jan 2099."""

        if not self._ShouldHandleRequest("/cache/expires"):
            return False

        self.send_response(200)
        self.send_header('Expires', 'Thu, 1 Jan 2099 00:00:00 GMT')
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheProxyRevalidateHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and allows caching for 60 seconds"""

        if not self._ShouldHandleRequest("/cache/proxy-revalidate"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=60, proxy-revalidate')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CachePrivateHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and allows caching for 5 seconds."""

        if not self._ShouldHandleRequest("/cache/private"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=3, private')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CachePublicHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and allows caching for 5 seconds."""

        if not self._ShouldHandleRequest("/cache/public"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=3, public')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheSMaxAgeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow for caching."""

        if not self._ShouldHandleRequest("/cache/s-maxage"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'public, s-maxage = 60, max-age = 0')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheMustRevalidateHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow caching."""

        if not self._ShouldHandleRequest("/cache/must-revalidate"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'must-revalidate')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheMustRevalidateMaxAgeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow caching event though max-age of 60
    seconds is specified."""

        if not self._ShouldHandleRequest("/cache/must-revalidate/max-age"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=60, must-revalidate')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheNoStoreHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow the page to be stored."""

        if not self._ShouldHandleRequest("/cache/no-store"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'no-store')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheNoStoreMaxAgeHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow the page to be stored even though max-age
    of 60 seconds is specified."""

        if not self._ShouldHandleRequest("/cache/no-store/max-age"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=60, no-store')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def CacheNoTransformHandler(self):
        """This request handler yields a page with the title set to the current
    system time, and does not allow the content to transformed during
    user-agent caching"""

        if not self._ShouldHandleRequest("/cache/no-transform"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'no-transform')
        self.end_headers()

        self.wfile.write('<html><head><title>%s</title></head></html>' %
                         time.time())

        return True

    def EchoHeader(self):
        """This handler echoes back the value of a specific request header."""
        """The only difference between this function and the EchoHeaderOverride"""
        """function is in the parameter being passed to the helper function"""
        return self.EchoHeaderHelper("/echoheader")

    def EchoHeaderOverride(self):
        """This handler echoes back the value of a specific request header."""
        """The UrlRequest unit tests also execute for ChromeFrame which uses"""
        """IE to issue HTTP requests using the host network stack."""
        """The Accept and Charset tests which expect the server to echo back"""
        """the corresponding headers fail here as IE returns cached responses"""
        """The EchoHeaderOverride parameter is an easy way to ensure that IE"""
        """treats this request as a new request and does not cache it."""
        return self.EchoHeaderHelper("/echoheaderoverride")

    def EchoHeaderHelper(self, echo_header):
        """This function echoes back the value of the request header passed in."""
        if not self._ShouldHandleRequest(echo_header):
            return False

        query_char = self.path.find('?')
        if query_char != -1:
            header_name = self.path[query_char + 1:]

        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.send_header('Cache-control', 'max-age=60000')
        # insert a vary header to properly indicate that the cachability of this
        # request is subject to value of the request header being echoed.
        if len(header_name) > 0:
            self.send_header('Vary', header_name)
        self.end_headers()

        if len(header_name) > 0:
            self.wfile.write(self.headers.getheader(header_name))

        return True

    def EchoHandler(self):
        """This handler just echoes back the payload of the request, for testing
    form submission."""

        if not self._ShouldHandleRequest("/echo"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        length = int(self.headers.getheader('content-length'))
        request = self.rfile.read(length)
        self.wfile.write(request)
        return True

    def WriteFile(self):
        """This is handler dumps the content of POST/PUT request to a disk file
    into the data_dir/dump. Sub-directories are not supported."""

        prefix = '/writefile/'
        if not self.path.startswith(prefix):
            return False

        file_name = self.path[len(prefix):]

        # do not allow fancy chars in file name
        re.sub('[^a-zA-Z0-9_.-]+', '', file_name)
        if len(file_name) and file_name[0] != '.':
            path = os.path.join(self.server.data_dir, 'dump', file_name)
            length = int(self.headers.getheader('content-length'))
            request = self.rfile.read(length)
            f = open(path, "wb")
            f.write(request)
            f.close()

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write('<html>%s</html>' % file_name)
        return True

    def EchoTitleHandler(self):
        """This handler is like Echo, but sets the page title to the request."""

        if not self._ShouldHandleRequest("/echotitle"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        length = int(self.headers.getheader('content-length'))
        request = self.rfile.read(length)
        self.wfile.write('<html><head><title>')
        self.wfile.write(request)
        self.wfile.write('</title></head></html>')
        return True

    def EchoAllHandler(self):
        """This handler yields a (more) human-readable page listing information
    about the request header & contents."""

        if not self._ShouldHandleRequest("/echoall"):
            return False

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(
            '<html><head><style>'
            'pre { border: 1px solid black; margin: 5px; padding: 5px }'
            '</style></head><body>'
            '<div style="float: right">'
            '<a href="http://localhost:8888/echo">back to referring page</a></div>'
            '<h1>Request Body:</h1><pre>')

        if self.command == 'POST' or self.command == 'PUT':
            length = int(self.headers.getheader('content-length'))
            qs = self.rfile.read(length)
            params = cgi.parse_qs(qs, keep_blank_values=1)

            for param in params:
                self.wfile.write('%s=%s\n' % (param, params[param][0]))

        self.wfile.write('</pre>')

        self.wfile.write('<h1>Request Headers:</h1><pre>%s</pre>' %
                         self.headers)

        self.wfile.write('</body></html>')
        return True

    def DownloadHandler(self):
        """This handler sends a downloadable file with or without reporting
    the size (6K)."""

        if self.path.startswith("/download-unknown-size"):
            send_length = False
        elif self.path.startswith("/download-known-size"):
            send_length = True
        else:
            return False

        #
        # The test which uses this functionality is attempting to send
        # small chunks of data to the client.  Use a fairly large buffer
        # so that we'll fill chrome's IO buffer enough to force it to
        # actually write the data.
        # See also the comments in the client-side of this test in
        # download_uitest.cc
        #
        size_chunk1 = 35 * 1024
        size_chunk2 = 10 * 1024

        self.send_response(200)
        self.send_header('Content-type', 'application/octet-stream')
        self.send_header('Cache-Control', 'max-age=0')
        if send_length:
            self.send_header('Content-Length', size_chunk1 + size_chunk2)
        self.end_headers()

        # First chunk of data:
        self.wfile.write("*" * size_chunk1)
        self.wfile.flush()

        # handle requests until one of them clears this flag.
        self.server.waitForDownload = True
        while self.server.waitForDownload:
            self.server.handle_request()

        # Second chunk of data:
        self.wfile.write("*" * size_chunk2)
        return True

    def DownloadFinishHandler(self):
        """This handler just tells the server to finish the current download."""

        if not self._ShouldHandleRequest("/download-finish"):
            return False

        self.server.waitForDownload = False
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.send_header('Cache-Control', 'max-age=0')
        self.end_headers()
        return True

    def FileHandler(self):
        """This handler sends the contents of the requested file.  Wow, it's like
    a real webserver!"""

        prefix = self.server.file_root_url
        if not self.path.startswith(prefix):
            return False

        # Consume a request body if present.
        if self.command == 'POST' or self.command == 'PUT':
            self.rfile.read(int(self.headers.getheader('content-length')))

        file = self.path[len(prefix):]
        if file.find('?') > -1:
            # Ignore the query parameters entirely.
            url, querystring = file.split('?')
        else:
            url = file
        entries = url.split('/')
        path = os.path.join(self.server.data_dir, *entries)
        if os.path.isdir(path):
            path = os.path.join(path, 'index.html')

        if not os.path.isfile(path):
            print "File not found " + file + " full path:" + path
            self.send_error(404)
            return True

        f = open(path, "rb")
        data = f.read()
        f.close()

        # If file.mock-http-headers exists, it contains the headers we
        # should send.  Read them in and parse them.
        headers_path = path + '.mock-http-headers'
        if os.path.isfile(headers_path):
            f = open(headers_path, "r")

            # "HTTP/1.1 200 OK"
            response = f.readline()
            status_code = re.findall('HTTP/\d+.\d+ (\d+)', response)[0]
            self.send_response(int(status_code))

            for line in f:
                header_values = re.findall('(\S+):\s*(.*)', line)
                if len(header_values) > 0:
                    # "name: value"
                    name, value = header_values[0]
                    self.send_header(name, value)
            f.close()
        else:
            # Could be more generic once we support mime-type sniffing, but for
            # now we need to set it explicitly.
            self.send_response(200)
            self.send_header('Content-type', self.GetMIMETypeFromName(file))
            self.send_header('Content-Length', len(data))
        self.end_headers()

        self.wfile.write(data)

        return True

    def RealFileWithCommonHeaderHandler(self):
        """This handler sends the contents of the requested file without the pseudo
    http head!"""

        prefix = '/realfiles/'
        if not self.path.startswith(prefix):
            return False

        file = self.path[len(prefix):]
        path = os.path.join(self.server.data_dir, file)

        try:
            f = open(path, "rb")
            data = f.read()
            f.close()

            # just simply set the MIME as octal stream
            self.send_response(200)
            self.send_header('Content-type', 'application/octet-stream')
            self.end_headers()

            self.wfile.write(data)
        except:
            self.send_error(404)

        return True

    def RealBZ2FileWithCommonHeaderHandler(self):
        """This handler sends the bzip2 contents of the requested file with
     corresponding Content-Encoding field in http head!"""

        prefix = '/realbz2files/'
        if not self.path.startswith(prefix):
            return False

        parts = self.path.split('?')
        file = parts[0][len(prefix):]
        path = os.path.join(self.server.data_dir, file) + '.bz2'

        if len(parts) > 1:
            options = parts[1]
        else:
            options = ''

        try:
            self.send_response(200)
            accept_encoding = self.headers.get("Accept-Encoding")
            if accept_encoding.find("bzip2") != -1:
                f = open(path, "rb")
                data = f.read()
                f.close()
                self.send_header('Content-Encoding', 'bzip2')
                self.send_header('Content-type', 'application/x-bzip2')
                self.end_headers()
                if options == 'incremental-header':
                    self.wfile.write(data[:1])
                    self.wfile.flush()
                    time.sleep(1.0)
                    self.wfile.write(data[1:])
                else:
                    self.wfile.write(data)
            else:
                """client do not support bzip2 format, send pseudo content
        """
                self.send_header('Content-type',
                                 'text/html; charset=ISO-8859-1')
                self.end_headers()
                self.wfile.write("you do not support bzip2 encoding")
        except:
            self.send_error(404)

        return True

    def SetCookieHandler(self):
        """This handler just sets a cookie, for testing cookie handling."""

        if not self._ShouldHandleRequest("/set-cookie"):
            return False

        query_char = self.path.find('?')
        if query_char != -1:
            cookie_values = self.path[query_char + 1:].split('&')
        else:
            cookie_values = ("", )
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        for cookie_value in cookie_values:
            self.send_header('Set-Cookie', '%s' % cookie_value)
        self.end_headers()
        for cookie_value in cookie_values:
            self.wfile.write('%s' % cookie_value)
        return True

    def AuthBasicHandler(self):
        """This handler tests 'Basic' authentication.  It just sends a page with
    title 'user/pass' if you succeed."""

        if not self._ShouldHandleRequest("/auth-basic"):
            return False

        username = userpass = password = b64str = ""

        set_cookie_if_challenged = self.path.find(
            '?set-cookie-if-challenged') > 0

        auth = self.headers.getheader('authorization')
        try:
            if not auth:
                raise Exception('no auth')
            b64str = re.findall(r'Basic (\S+)', auth)[0]
            userpass = base64.b64decode(b64str)
            username, password = re.findall(r'([^:]+):(\S+)', userpass)[0]
            if password != 'secret':
                raise Exception('wrong password')
        except Exception, e:
            # Authentication failed.
            self.send_response(401)
            self.send_header('WWW-Authenticate', 'Basic realm="testrealm"')
            self.send_header('Content-type', 'text/html')
            if set_cookie_if_challenged:
                self.send_header('Set-Cookie', 'got_challenged=true')
            self.end_headers()
            self.wfile.write('<html><head>')
            self.wfile.write('<title>Denied: %s</title>' % e)
            self.wfile.write('</head><body>')
            self.wfile.write('auth=%s<p>' % auth)
            self.wfile.write('b64str=%s<p>' % b64str)
            self.wfile.write('username: %s<p>' % username)
            self.wfile.write('userpass: %s<p>' % userpass)
            self.wfile.write('password: %s<p>' % password)
            self.wfile.write('You sent:<br>%s<p>' % self.headers)
            self.wfile.write('</body></html>')
            return True

        # Authentication successful.  (Return a cachable response to allow for
        # testing cached pages that require authentication.)
        if_none_match = self.headers.getheader('if-none-match')
        if if_none_match == "abc":
            self.send_response(304)
            self.end_headers()
        else:
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.send_header('Cache-control', 'max-age=60000')
            self.send_header('Etag', 'abc')
            self.end_headers()
            self.wfile.write('<html><head>')
            self.wfile.write('<title>%s/%s</title>' % (username, password))
            self.wfile.write('</head><body>')
            self.wfile.write('auth=%s<p>' % auth)
            self.wfile.write('You sent:<br>%s<p>' % self.headers)
            self.wfile.write('</body></html>')

        return True