testing/web-platform/tests/tools/webdriver/webdriver/transport.py
author James Graham <james@hoppipolla.co.uk>
Thu, 23 Mar 2017 18:19:45 +0000
changeset 503910 83d9d8f3dfb82acec527654eb596ffca6aba22a4
parent 500771 ee95fa01ccd9d290f446b3f9b15d77f369d7c2f7
child 562187 e7024412b94e1afe296d8e804c2da30fd9e33858
permissions -rw-r--r--
Bug 1318724 - Increase the HTTP connection timeout for WebDriver tests, r=ato The 5s timeout was not enough for debug builds. I don't really see a reason to use something other than the default socket timeout here. MozReview-Commit-ID: Fm5lgSI3lFb

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

import httplib
import json
import urlparse


class Response(object):
    """Describes an HTTP response received from a remote en"Describes an HTTP
    response received from a remote end whose body has been read and parsed as
    appropriate."""
    def __init__(self, status, body):
        self.status = status
        self.body = body

    def __repr__(self):
        return "wdclient.Response(status=%d, body=%s)" % (self.status, self.body)

    @classmethod
    def from_http_response(cls, http_response):
        status = http_response.status
        body = http_response.read()

        # SpecID: dfn-send-a-response
        #
        # > 3. Set the response's header with name and value with the following
        # >    values:
        # >
        # >    "Content-Type"
        # >       "application/json; charset=utf-8"
        # >    "cache-control"
        # >       "no-cache"
        assert http_response.getheader("Content-Type") == "application/json; charset=utf-8"
        assert http_response.getheader("Cache-Control") == "no-cache"

        if body:
            body = json.loads(body)

            # SpecID: dfn-send-a-response
            #
            # > 4. If data is not null, let response's body be a JSON Object
            #      with a key `value` set to the JSON Serialization of data.
            assert "value" in body

        return cls(status, body)


class HTTPWireProtocol(object):
    """Transports messages (commands and responses) over the WebDriver
    wire protocol.
    """

    def __init__(self, host, port, url_prefix="/", timeout=None):
        """Construct interface for communicating with the remote server.

        :param url: URL of remote WebDriver server.
        :param wait: Duration to wait for remote to appear.
        """

        self.host = host
        self.port = port
        self.url_prefix = url_prefix

        self._timeout = timeout

    def url(self, suffix):
        return urlparse.urljoin(self.path_prefix, suffix)

    def send(self, method, url, body=None, headers=None):
        """Send a command to the remote.

        :param method: "POST" or "GET".
        :param url: "command part" of the requests URL path
        :param body: Body of the request.  Defaults to an empty dictionary
            if ``method`` is "POST".
        :param headers: Additional headers to include in the request.
        :return: an instance of wdclient.Response describing the HTTP response
            received from the remote end.
        """

        if body is None and method == "POST":
            body = {}

        if isinstance(body, dict):
            body = json.dumps(body)

        if isinstance(body, unicode):
            body = body.encode("utf-8")

        if headers is None:
            headers = {}

        url = self.url_prefix + url

        kwargs = {}
        if self._timeout is not None:
            kwargs["timeout"] = self._timeout

        conn = httplib.HTTPConnection(
            self.host, self.port, strict=True, **kwargs)
        conn.request(method, url, body, headers)

        try:
            response = Response.from_http_response(conn.getresponse())
        finally:
            conn.close()

        return response