Example #1
0
    def test_HTTP11_pipelining(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest("GET", "/hello", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(ntob('GET /hello?%s HTTP/1.1' % trial))
            conn._output(ntob("Host: %s" % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method="GET")
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, ntob("Hello, world!"))

        # Retrieve final response
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, ntob("Hello, world!"))

        conn.close()
Example #2
0
 def output(self):
     if self.body is None:
         return []
     elif isinstance(self.body, (tuple, list)):
         return [ntob(x) for x in self.body]
     else:
         return [ntob(self.body)]
Example #3
0
 def output(self):
     if self.body is None:
         return []
     elif isinstance(self.body, (tuple, list)):
         return [ntob(x) for x in self.body]
     else:
         return [ntob(self.body)]
Example #4
0
 def test_empty_string_app(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     return [
         ntob('Hello'), ntob(''), ntob(' '), ntob(''), ntob('world')
     ]
Example #5
0
    def test_HTTP11_pipelining(self):
        self.httpserver.protocol = 'HTTP/1.1'
        self.PROTOCOL = 'HTTP/1.1'

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest('GET', '/hello', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(ntob('GET /hello?%s HTTP/1.1' % trial))
            conn._output(ntob('Host: %s' % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method='GET')
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, b'Hello, world!')

        # Retrieve final response
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, b'Hello, world!')

        conn.close()
Example #6
0
    def test_100_Continue(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        self.persistent = True
        conn = self.HTTP_CONN

        # Try a page without an Expect request header first.
        # Note that httplib's response.begin automatically ignores
        # 100 Continue responses, so we must manually check for it.
        try:
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '4')
            conn.endheaders()
            conn.send(ntob("d'oh"))
            response = conn.response_class(conn.sock, method='POST')
            version, status, reason = response._read_status()
            self.assertNotEqual(status, 100)
        finally:
            conn.close()

        # Now try a page with an Expect header...
        try:
            conn.connect()
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '17')
            conn.putheader('Expect', '100-continue')
            conn.endheaders()
            response = conn.response_class(conn.sock, method='POST')

            # ...assert and then skip the 100 response
            version, status, reason = response._read_status()
            self.assertEqual(status, 100)
            while True:
                line = response.fp.readline().strip()
                if line:
                    self.fail(
                        '100 Continue should not output any headers. Got %r' %
                        line)
                else:
                    break

            # ...send the body
            body = ntob('I am a small file')
            conn.send(body)

            # ...get the final response
            response.begin()
            self.status, self.headers, self.body = webtest.shb(response)
            self.assertStatus(200)
            self.assertBody("thanks for '%s'" % body)
        finally:
            conn.close()
Example #7
0
    def test_100_Continue(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        self.persistent = True
        conn = self.HTTP_CONN

        # Try a page without an Expect request header first.
        # Note that httplib's response.begin automatically ignores
        # 100 Continue responses, so we must manually check for it.
        try:
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '4')
            conn.endheaders()
            conn.send(ntob("d'oh"))
            response = conn.response_class(conn.sock, method='POST')
            version, status, reason = response._read_status()
            self.assertNotEqual(status, 100)
        finally:
            conn.close()

        # Now try a page with an Expect header...
        try:
            conn.connect()
            conn.putrequest('POST', '/upload', skip_host=True)
            conn.putheader('Host', self.HOST)
            conn.putheader('Content-Type', 'text/plain')
            conn.putheader('Content-Length', '17')
            conn.putheader('Expect', '100-continue')
            conn.endheaders()
            response = conn.response_class(conn.sock, method='POST')

            # ...assert and then skip the 100 response
            version, status, reason = response._read_status()
            self.assertEqual(status, 100)
            while True:
                line = response.fp.readline().strip()
                if line:
                    self.fail(
                        '100 Continue should not output any headers. Got %r' %
                        line)
                else:
                    break

            # ...send the body
            body = ntob('I am a small file')
            conn.send(body)

            # ...get the final response
            response.begin()
            self.status, self.headers, self.body = webtest.shb(response)
            self.assertStatus(200)
            self.assertBody("thanks for '%s'" % body)
        finally:
            conn.close()
Example #8
0
 def output(self):
     if self.body is None:
         return []
     elif isinstance(self.body, six.text_type):
         return [ntob(self.body)]
     elif isinstance(self.body, six.binary_type):
         return [self.body]
     else:
         return [ntob(x) for x in self.body]
Example #9
0
 def bar(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain'),
                         ('Content-Length', '3')]
     write = start_response(status, response_headers)
     write(ntob('boo'))
     # This should fail according to the WSGI spec.
     try:
         noname
     except NameError:
         start_response(status, response_headers, sys.exc_info())
     return [ntob('Hello world')]
Example #10
0
    def test_100_Continue(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        self.persistent = True
        conn = self.HTTP_CONN

        # Try a page without an Expect request header first.
        # Note that httplib's response.begin automatically ignores
        # 100 Continue responses, so we must manually check for it.
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Content-Type", "text/plain")
        conn.putheader("Content-Length", "4")
        conn.endheaders()
        conn.send(ntob("d'oh"))
        response = conn.response_class(conn.sock, method="POST")
        version, status, reason = response._read_status()
        self.assertNotEqual(status, 100)
        conn.close()

        # Now try a page with an Expect header...
        conn.connect()
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Content-Type", "text/plain")
        conn.putheader("Content-Length", "17")
        conn.putheader("Expect", "100-continue")
        conn.endheaders()
        response = conn.response_class(conn.sock, method="POST")

        # ...assert and then skip the 100 response
        version, status, reason = response._read_status()
        self.assertEqual(status, 100)
        while True:
            line = response.fp.readline().strip()
            if line:
                self.fail(
                    "100 Continue should not output any headers. Got %r" %
                    line)
            else:
                break

        # ...send the body
        body = ntob("I am a small file")
        conn.send(body)

        # ...get the final response
        response.begin()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(200)
        self.assertBody("thanks for '%s'" % body)
        conn.close()
Example #11
0
 def bar(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain'),
                         ('Content-Length', '3')]
     write = start_response(status, response_headers)
     write(ntob('boo'))
     # This should fail according to the WSGI spec.
     try:
         noname
     except NameError:
         start_response(status, response_headers, sys.exc_info())
     return [ntob('Hello world')]
Example #12
0
    def test_100_Continue(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        self.persistent = True
        conn = self.HTTP_CONN

        # Try a page without an Expect request header first.
        # Note that httplib's response.begin automatically ignores
        # 100 Continue responses, so we must manually check for it.
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Content-Type", "text/plain")
        conn.putheader("Content-Length", "4")
        conn.endheaders()
        conn.send(ntob("d'oh"))
        response = conn.response_class(conn.sock, method="POST")
        version, status, reason = response._read_status()
        self.assertNotEqual(status, 100)
        conn.close()

        # Now try a page with an Expect header...
        conn.connect()
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Content-Type", "text/plain")
        conn.putheader("Content-Length", "17")
        conn.putheader("Expect", "100-continue")
        conn.endheaders()
        response = conn.response_class(conn.sock, method="POST")

        # ...assert and then skip the 100 response
        version, status, reason = response._read_status()
        self.assertEqual(status, 100)
        while True:
            line = response.fp.readline().strip()
            if line:
                self.fail("100 Continue should not output any headers. Got %r" % line)
            else:
                break

        # ...send the body
        body = ntob("I am a small file")
        conn.send(body)

        # ...get the final response
        response.begin()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(200)
        self.assertBody("thanks for '%s'" % body)
        conn.close()
Example #13
0
    def test_Chunked_Encoding(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        if (hasattr(self, 'harness') and
                'modpython' in self.harness.__class__.__name__.lower()):
            # mod_python forbids chunked encoding
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Set our HTTP_CONN to an instance so it persists between requests.
        self.persistent = True
        conn = self.HTTP_CONN

        # Try a normal chunked request (with extensions)
        body = ntob('8;key=value\r\nxx\r\nxxxx\r\n5\r\nyyyyy\r\n0\r\n'
                    'Content-Type: application/json\r\n'
                    '\r\n')
        conn.putrequest('POST', '/upload', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.putheader('Transfer-Encoding', 'chunked')
        conn.putheader('Trailer', 'Content-Type')
        # Note that this is somewhat malformed:
        # we shouldn't be sending Content-Length.
        # RFC 2616 says the server should ignore it.
        conn.putheader('Content-Length', '3')
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus('200 OK')
        self.assertBody("thanks for '%s'" % ntob('xx\r\nxxxxyyyyy'))

        # Try a chunked request that exceeds server.max_request_body_size.
        # Note that the delimiters and trailer are included.
        body = ntob('3e3\r\n' + ('x' * 995) + '\r\n0\r\n\r\n')
        conn.putrequest('POST', '/upload', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.putheader('Transfer-Encoding', 'chunked')
        conn.putheader('Content-Type', 'text/plain')
        # Chunked requests don't need a content-length
        ##        conn.putheader("Content-Length", len(body))
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(413)
        conn.close()
Example #14
0
    def test_Chunked_Encoding(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        if (hasattr(self, 'harness')
                and 'modpython' in self.harness.__class__.__name__.lower()):
            # mod_python forbids chunked encoding
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Set our HTTP_CONN to an instance so it persists between requests.
        self.persistent = True
        conn = self.HTTP_CONN

        # Try a normal chunked request (with extensions)
        body = ntob('8;key=value\r\nxx\r\nxxxx\r\n5\r\nyyyyy\r\n0\r\n'
                    'Content-Type: application/json\r\n'
                    '\r\n')
        conn.putrequest('POST', '/upload', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.putheader('Transfer-Encoding', 'chunked')
        conn.putheader('Trailer', 'Content-Type')
        # Note that this is somewhat malformed:
        # we shouldn't be sending Content-Length.
        # RFC 2616 says the server should ignore it.
        conn.putheader('Content-Length', '3')
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus('200 OK')
        self.assertBody("thanks for '%s'" % ntob('xx\r\nxxxxyyyyy'))

        # Try a chunked request that exceeds server.max_request_body_size.
        # Note that the delimiters and trailer are included.
        body = ntob('3e3\r\n' + ('x' * 995) + '\r\n0\r\n\r\n')
        conn.putrequest('POST', '/upload', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.putheader('Transfer-Encoding', 'chunked')
        conn.putheader('Content-Type', 'text/plain')
        # Chunked requests don't need a content-length
        ##        conn.putheader("Content-Length", len(body))
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(413)
        conn.close()
Example #15
0
 def putrequest(self, method, url):
     if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
         self._HTTPConnection__response = None
     
     if self._HTTPConnection__state == http.client._CS_IDLE:
         self._HTTPConnection__state = http.client._CS_REQ_STARTED
     else:
         raise http.client.CannotSendRequest()
     
     self._method = method
     if not url:
         url = ntob('/')
     request = ntob(' ').join((method.encode("ASCII"), url,
                               self._http_vsn_str.encode("ASCII")))
     self._output(request)
Example #16
0
 def foo(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     # This should fail according to the WSGI spec.
     start_response(status, response_headers)
     return [ntob('Hello world')]
Example #17
0
 def __call__(self, environ, start_response):
     req, resp = Request(environ), Response()
     try:
         # Recode handler name as Python supports unicode method names
         # and we should try match those first.
         # Source of the idea: cherrypy._cpwsgi.AppResponse.recode_path_qs
         latin1_handler_name = environ['PATH_INFO'].lstrip('/').replace(
             '/', '_')
         try:
             unicode_handler_name = bton(ntob(latin1_handler_name), 'utf-8')
             handler = getattr(self, unicode_handler_name)
         except (UnicodeError, AttributeError):
             handler = getattr(self, latin1_handler_name)
     except AttributeError:
         resp.status = '404 Not Found'
     else:
         output = handler(req, resp)
         if (output is not None and not any(
                 resp.status.startswith(status_code)
                 for status_code in ('204', '304'))):
             resp.body = output
             try:
                 resp.headers.setdefault('Content-Length', str(len(output)))
             except TypeError:
                 if not isinstance(output, types.GeneratorType):
                     raise
     start_response(resp.status, resp.headers.items())
     return resp.output()
Example #18
0
 def test_garbage_in(self):
     # Connect without SSL regardless of server.scheme
     c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c._output(ntob('gjkgjklsgjklsgjkljklsg'))
     c._send_output()
     response = c.response_class(c.sock, method='GET')
     try:
         response.begin()
         self.assertEqual(response.status, 400)
         self.assertEqual(response.fp.read(22),
                          ntob('Malformed Request-Line'))
         c.close()
     except socket.error as ex:
         # "Connection reset by peer" is also acceptable.
         if ex.errno != errno.ECONNRESET:
             raise
Example #19
0
 def test_status_syntax_error(self):
     self.getPage("/bad")
     self.assertStatus(500)
     self.assertStatus(500)
     self.assertInBody(
         "Illegal response status from server (%s is non-numeric)." %
         (repr(ntob('error'))))
Example #20
0
 def test_status_syntax_error(self):
     self.getPage("/bad")
     self.assertStatus(500)
     self.assertStatus(500)
     self.assertInBody(
         "Illegal response status from server (%s is non-numeric)." %
         (repr(ntob('error'))))
Example #21
0
    def test_parse_uri_unsafe_uri(self):
        """Test that malicious URI does not allow HTTP injection.

        This effectively checks that sending GET request with URL

        /%A0%D0blah%20key%200%20900%204%20data

        is not converted into

        GET /
        blah key 0 900 4 data
        HTTP/1.1

        which would be a security issue otherwise.
        """
        c = self._get_http_connection()
        c._output(
            ntob('GET /%A0%D0blah%20key%200%20900%204%20data HTTP/1.1',
                 'utf-8'))
        c._send_output()
        response = self._get_http_response(c, method='GET')
        response.begin()
        assert response.status == HTTP_OK
        assert response.fp.read(12) == b'Hello world!'
        c.close()
Example #22
0
 def test_garbage_in(self):
     # Connect without SSL regardless of server.scheme
     c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c._output(ntob('gjkgjklsgjklsgjkljklsg'))
     c._send_output()
     response = c.response_class(c.sock, method="GET")
     try:
         response.begin()
         self.assertEqual(response.status, 400)
         self.assertEqual(response.fp.read(22), ntob("Malformed Request-Line"))
         c.close()
     except socket.error:
         e = sys.exc_info()[1]
         # "Connection reset by peer" is also acceptable.
         if e.errno != errno.ECONNRESET:
             raise
Example #23
0
 def foo(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     # This should fail according to the WSGI spec.
     start_response(status, response_headers)
     return [ntob('Hello world')]
Example #24
0
    def test_queue_full(self):
        conns = []
        overflow_conn = None

        try:
            # Make 15 initial requests and leave them open, which should use
            # all of wsgiserver's WorkerThreads and fill its Queue.
            for i in range(15):
                conn = self.HTTP_CONN(self.HOST, self.PORT)
                conn.putrequest('POST', '/upload', skip_host=True)
                conn.putheader('Host', self.HOST)
                conn.putheader('Content-Type', 'text/plain')
                conn.putheader('Content-Length', '4')
                conn.endheaders()
                conns.append(conn)

            # Now try a 16th conn, which should be closed by the server immediately.
            overflow_conn = self.HTTP_CONN(self.HOST, self.PORT)
            # Manually connect since httplib won't let us set a timeout
            for res in socket.getaddrinfo(self.HOST, self.PORT, 0,
                                          socket.SOCK_STREAM):
                af, socktype, proto, canonname, sa = res
                overflow_conn.sock = socket.socket(af, socktype, proto)
                overflow_conn.sock.settimeout(5)
                overflow_conn.sock.connect(sa)
                break

            overflow_conn.putrequest('GET', '/', skip_host=True)
            overflow_conn.putheader('Host', self.HOST)
            overflow_conn.endheaders()
            response = overflow_conn.response_class(overflow_conn.sock, method='GET')
            try:
                response.begin()
            except socket.error as exc:
                if exc.args[0] in socket_reset_errors:
                    pass # Expected.
                else:
                    tmpl = (
                        'Overflow conn did not get RST. '
                        'Got {exc.args!r} instead'
                    )
                    raise AssertionError(tmpl.format(**locals()))
            except BadStatusLine:
                # This is a special case in OS X. Linux and Windows will
                # RST correctly.
                assert sys.platform == 'darwin'
            else:
                raise AssertionError('Overflow conn did not get RST ')
        finally:
            for conn in conns:
                conn.send(ntob('done'))
                response = conn.response_class(conn.sock, method='POST')
                response.begin()
                self.body = response.read()
                self.assertBody("thanks for 'done'")
                self.assertEqual(response.status, 200)
                conn.close()
            if overflow_conn:
                overflow_conn.close()
Example #25
0
    def test_queue_full(self):
        conns = []
        overflow_conn = None

        try:
            # Make 15 initial requests and leave them open, which should use
            # all of wsgiserver's WorkerThreads and fill its Queue.
            for i in range(15):
                conn = self.HTTP_CONN(self.HOST, self.PORT)
                conn.putrequest('POST', '/upload', skip_host=True)
                conn.putheader('Host', self.HOST)
                conn.putheader('Content-Type', 'text/plain')
                conn.putheader('Content-Length', '4')
                conn.endheaders()
                conns.append(conn)

            # Now try a 16th conn, which should be closed by the server immediately.
            overflow_conn = self.HTTP_CONN(self.HOST, self.PORT)
            # Manually connect since httplib won't let us set a timeout
            for res in socket.getaddrinfo(self.HOST, self.PORT, 0,
                                          socket.SOCK_STREAM):
                af, socktype, proto, canonname, sa = res
                overflow_conn.sock = socket.socket(af, socktype, proto)
                overflow_conn.sock.settimeout(5)
                overflow_conn.sock.connect(sa)
                break

            overflow_conn.putrequest('GET', '/', skip_host=True)
            overflow_conn.putheader('Host', self.HOST)
            overflow_conn.endheaders()
            response = overflow_conn.response_class(overflow_conn.sock,
                                                    method='GET')
            try:
                response.begin()
            except socket.error as exc:
                if exc.args[0] in socket_reset_errors:
                    pass  # Expected.
                else:
                    tmpl = ('Overflow conn did not get RST. '
                            'Got {exc.args!r} instead')
                    raise AssertionError(tmpl.format(**locals()))
            except BadStatusLine:
                # This is a special case in OS X. Linux and Windows will
                # RST correctly.
                assert sys.platform == 'darwin'
            else:
                raise AssertionError('Overflow conn did not get RST ')
        finally:
            for conn in conns:
                conn.send(ntob('done'))
                response = conn.response_class(conn.sock, method='POST')
                response.begin()
                self.body = response.read()
                self.assertBody("thanks for 'done'")
                self.assertEqual(response.status, 200)
                conn.close()
            if overflow_conn:
                overflow_conn.close()
Example #26
0
    def test_No_CRLF(self):
        self.persistent = True

        conn = self.HTTP_CONN
        conn.send(ntob('GET /hello HTTP/1.1\n\n'))
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.body = response.read()
        self.assertBody('HTTP requires CRLF terminators')
        conn.close()

        conn.connect()
        conn.send(ntob('GET /hello HTTP/1.1\r\n\n'))
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.body = response.read()
        self.assertBody('HTTP requires CRLF terminators')
        conn.close()
Example #27
0
 def test_malformed_request_line(self):
     # Test missing version in Request-Line
     if self.scheme == 'https':
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c._output(ntob('GET /'))
     c._send_output()
     if hasattr(c, 'strict'):
         response = c.response_class(c.sock, strict=c.strict, method='GET')
     else:
         # Python 3.2 removed the 'strict' feature, saying:
         # "http.client now always assumes HTTP/1.x compliant servers."
         response = c.response_class(c.sock, method='GET')
     response.begin()
     self.assertEqual(response.status, 400)
     self.assertEqual(response.fp.read(22), ntob("Malformed Request-Line"))
     c.close()
Example #28
0
 def test_malformed_request_line(self):
     # Test missing version in Request-Line
     if self.scheme == 'https':
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c._output(ntob('GET /'))
     c._send_output()
     if hasattr(c, 'strict'):
         response = c.response_class(c.sock, strict=c.strict, method='GET')
     else:
         # Python 3.2 removed the 'strict' feature, saying:
         # "http.client now always assumes HTTP/1.x compliant servers."
         response = c.response_class(c.sock, method='GET')
     response.begin()
     self.assertEqual(response.status, 400)
     self.assertEqual(response.fp.read(22), ntob("Malformed Request-Line"))
     c.close()
Example #29
0
    def test_malformed_request_line(self):
        if getattr(cherrypy.server, 'using_apache', False):
            return self.skip('skipped due to known Apache differences...')

        # Test missing version in Request-Line
        c = self.make_connection()
        c._output(ntob('GET /'))
        c._send_output()
        if hasattr(c, 'strict'):
            response = c.response_class(c.sock, strict=c.strict, method='GET')
        else:
            # Python 3.2 removed the 'strict' feature, saying:
            # "http.client now always assumes HTTP/1.x compliant servers."
            response = c.response_class(c.sock, method='GET')
        response.begin()
        self.assertEqual(response.status, 400)
        self.assertEqual(response.fp.read(22), ntob('Malformed Request-Line'))
        c.close()
Example #30
0
    def test_No_CRLF(self):
        self.persistent = True

        conn = self.HTTP_CONN
        conn.send(ntob('GET /hello HTTP/1.1\n\n'))
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.body = response.read()
        self.assertBody('HTTP requires CRLF terminators')
        conn.close()

        conn.connect()
        conn.send(ntob('GET /hello HTTP/1.1\r\n\n'))
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.body = response.read()
        self.assertBody('HTTP requires CRLF terminators')
        conn.close()
Example #31
0
    def start_response(self, status, headers, exc_info=None):
        """WSGI callable to begin the HTTP response."""
        # "The application may call start_response more than once,
        # if and only if the exc_info argument is provided."
        if self.started_response and not exc_info:
            raise AssertionError("WSGI start_response called a second "
                                 "time with no exc_info.")
        self.started_response = True
        
        # "if exc_info is provided, and the HTTP headers have already been
        # sent, start_response must raise an error, and should raise the
        # exc_info tuple."
        if (exc_info is not None) and self.req.sent_headers:
            try:
                if py3k:
                    raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
                else:
                    raise (exc_info[0], exc_info[1], exc_info[2])
            finally:
                exc_info = None

        # According to PEP 3333, when using Python 3, the response status
        # and headers must be bytes masquerading as unicode; that is, they
        # must be of type "str" but are restricted to code points in the
        # "latin-1" set.
        if not isinstance(status, str):
            raise TypeError("WSGI response status is not of type str.")
        self.req.status = ntob(status)

        for k, v in headers:
            if not isinstance(k, str):
                raise TypeError(
                    "WSGI response header key %s is not of type str." %
                    repr(k))
            if not isinstance(v, str):
                raise TypeError(
                    "WSGI response header value %s is not of type str." %
                    repr(v))
            if k.lower() == 'content-length':
                self.remaining_bytes_out = int(v)
            self.req.outheaders.append((ntob(k), ntob(v)))
        
        return self.write
Example #32
0
    def start_response(self, status, headers, exc_info=None):
        """WSGI callable to begin the HTTP response."""
        # "The application may call start_response more than once,
        # if and only if the exc_info argument is provided."
        if self.started_response and not exc_info:
            raise AssertionError("WSGI start_response called a second "
                                 "time with no exc_info.")
        self.started_response = True

        # "if exc_info is provided, and the HTTP headers have already been
        # sent, start_response must raise an error, and should raise the
        # exc_info tuple."
        if (exc_info is not None) and self.req.sent_headers:
            try:
                if py3k:
                    raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
                else:
                    raise (exc_info[0], exc_info[1], exc_info[2])
            finally:
                exc_info = None

        # According to PEP 3333, when using Python 3, the response status
        # and headers must be bytes masquerading as unicode; that is, they
        # must be of type "str" but are restricted to code points in the
        # "latin-1" set.
        if not isinstance(status, str):
            raise TypeError("WSGI response status is not of type str.")
        self.req.status = ntob(status)

        for k, v in headers:
            if not isinstance(k, str):
                raise TypeError(
                    "WSGI response header key %s is not of type str." %
                    repr(k))
            if not isinstance(v, str):
                raise TypeError(
                    "WSGI response header value %s is not of type str." %
                    repr(v))
            if k.lower() == 'content-length':
                self.remaining_bytes_out = int(v)
            self.req.outheaders.append((ntob(k), ntob(v)))

        return self.write
Example #33
0
    def test_HTTP11_pipelining(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest('GET', '/hello', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(ntob('GET /hello HTTP/1.1'))
            conn._output(ntob('Host: %s' % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method='GET')
            # there is a bug in python3 regarding the buffering of
            # ``conn.sock``. Until that bug get's fixed we will
            # monkey patch the ``reponse`` instance.
            # https://bugs.python.org/issue23377
            if six.PY3:
                response.fp = conn.sock.makefile('rb', 0)
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, ntob('Hello, world!'))

        # Retrieve final response
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, ntob('Hello, world!'))

        conn.close()
Example #34
0
    def _test_Chunked_Encoding(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        # Set our HTTP_CONN to an instance so it persists between requests.
        self.persistent = True
        conn = self.HTTP_CONN

        # Try a normal chunked request (with extensions)
        body = ntob("8;key=value\r\nxx\r\nxxxx\r\n5\r\nyyyyy\r\n0\r\n"
                    "Content-Type: application/json\r\n"
                    "\r\n")
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Transfer-Encoding", "chunked")
        conn.putheader("Trailer", "Content-Type")
        # Note that this is somewhat malformed:
        # we shouldn't be sending Content-Length.
        # RFC 2616 says the server should ignore it.
        conn.putheader("Content-Length", "3")
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus('200 OK')
        self.assertBody("thanks for '%s'" % ntob('xx\r\nxxxxyyyyy'))

        # Try a chunked request that exceeds server.max_request_body_size.
        # Note that the delimiters and trailer are included.
        body = ntob("3e3\r\n" + ("x" * 995) + "\r\n0\r\n\r\n")
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Transfer-Encoding", "chunked")
        conn.putheader("Content-Type", "text/plain")
        # Chunked requests don't need a content-length
        ##        conn.putheader("Content-Length", len(body))
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(413)
        conn.close()
Example #35
0
    def test_HTTP11_pipelining(self):
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Test pipelining. httplib doesn't support this directly.
        self.persistent = True
        conn = self.HTTP_CONN

        # Put request 1
        conn.putrequest('GET', '/hello', skip_host=True)
        conn.putheader('Host', self.HOST)
        conn.endheaders()

        for trial in range(5):
            # Put next request
            conn._output(ntob('GET /hello HTTP/1.1'))
            conn._output(ntob('Host: %s' % self.HOST, 'ascii'))
            conn._send_output()

            # Retrieve previous response
            response = conn.response_class(conn.sock, method='GET')
            # there is a bug in python3 regarding the buffering of
            # ``conn.sock``. Until that bug get's fixed we will
            # monkey patch the ``reponse`` instance.
            # https://bugs.python.org/issue23377
            if six.PY3:
                response.fp = conn.sock.makefile('rb', 0)
            response.begin()
            body = response.read(13)
            self.assertEqual(response.status, 200)
            self.assertEqual(body, ntob('Hello, world!'))

        # Retrieve final response
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        body = response.read()
        self.assertEqual(response.status, 200)
        self.assertEqual(body, ntob('Hello, world!'))

        conn.close()
Example #36
0
    def _test_Chunked_Encoding(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        # Set our HTTP_CONN to an instance so it persists between requests.
        self.persistent = True
        conn = self.HTTP_CONN

        # Try a normal chunked request (with extensions)
        body = ntob("8;key=value\r\nxx\r\nxxxx\r\n5\r\nyyyyy\r\n0\r\n"
                "Content-Type: application/json\r\n"
                "\r\n")
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Transfer-Encoding", "chunked")
        conn.putheader("Trailer", "Content-Type")
        # Note that this is somewhat malformed:
        # we shouldn't be sending Content-Length.
        # RFC 2616 says the server should ignore it.
        conn.putheader("Content-Length", "3")
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus('200 OK')
        self.assertBody("thanks for '%s'" % ntob('xx\r\nxxxxyyyyy'))

        # Try a chunked request that exceeds server.max_request_body_size.
        # Note that the delimiters and trailer are included.
        body = ntob("3e3\r\n" + ("x" * 995) + "\r\n0\r\n\r\n")
        conn.putrequest("POST", "/upload", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.putheader("Transfer-Encoding", "chunked")
        conn.putheader("Content-Type", "text/plain")
        # Chunked requests don't need a content-length
##        conn.putheader("Content-Length", len(body))
        conn.endheaders()
        conn.send(body)
        response = conn.getresponse()
        self.status, self.headers, self.body = webtest.shb(response)
        self.assertStatus(413)
        conn.close()
Example #37
0
    def test_No_CRLF(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"
        self.persistent = True

        conn = self.HTTP_CONN
        conn.send(ntob('GET /hello HTTP/1.1\n\n'))
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.body = response.read()
        self.assertBody("HTTP requires CRLF terminators")
        conn.close()

        conn.connect()
        conn.send(ntob('GET /hello HTTP/1.1\r\n\n'))
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.body = response.read()
        self.assertBody("HTTP requires CRLF terminators")
        conn.close()
Example #38
0
    def test_No_CRLF(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"
        self.persistent = True

        conn = self.HTTP_CONN
        conn.send(ntob('GET /hello HTTP/1.1\n\n'))
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.body = response.read()
        self.assertBody("HTTP requires CRLF terminators")
        conn.close()

        conn.connect()
        conn.send(ntob('GET /hello HTTP/1.1\r\n\n'))
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.body = response.read()
        self.assertBody("HTTP requires CRLF terminators")
        conn.close()
Example #39
0
 def test_app(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     output = ['Hello, world!\n',
               'This is a wsgi app running within CherryPy!\n\n']
     keys = list(environ.keys())
     keys.sort()
     for k in keys:
         output.append('%s: %s\n' % (k, environ[k]))
     return [ntob(x, 'utf-8') for x in output]
Example #40
0
 def test_app(environ, start_response):
     status = '200 OK'
     response_headers = [('Content-type', 'text/plain')]
     start_response(status, response_headers)
     output = ['Hello, world!\n',
               'This is a wsgi app running within Cheroot!\n\n']
     keys = list(environ.keys())
     keys.sort()
     for k in keys:
         output.append('%s: %s\n' % (k,environ[k]))
     return [ntob(x, 'utf-8') for x in output]
Example #41
0
    def test_parse_uri_invalid_uri(self):
        c = self._get_http_connection()
        c._output(ntob('GET /йопта! HTTP/1.1', 'utf-8'))
        c._send_output()
        response = self._get_http_response(c, method='GET')
        response.begin()
        assert response.status == HTTP_BAD_REQUEST
        assert response.fp.read(21) == b'Malformed Request-URI'
        c.close()

        for uri in ['hello', url_quote('привіт')]:
            self.getPage(uri)
            self.assertStatus(HTTP_BAD_REQUEST)
Example #42
0
    def test_malformed_header(self):
        c = self.make_connection()
        c.putrequest('GET', '/')
        c.putheader('Content-Type', 'text/plain')
        # See https://github.com/cherrypy/cherrypy/issues/941
        c._output(ntob('Re, 1.2.3.4#015#012'))
        c.endheaders()

        response = c.getresponse()
        self.status = str(response.status)
        self.assertStatus(400)
        self.body = response.fp.read(20)
        self.assertBody('Illegal header line.')
Example #43
0
 def test_chunked_request_payload_readline(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo_lines")
     c.putheader("Transfer-Encoding", "chunked")
     c.endheaders()
     c.send(ntob("13\r\nI am a\nrequest body\r\n0\r\n\r\n"))
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(200)
     self.assertBody("I am a\nrequest body")
Example #44
0
 def test_chunked_request_payload_readline(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo_lines")
     c.putheader("Transfer-Encoding", "chunked")
     c.endheaders()
     c.send(ntob("13\r\nI am a\nrequest body\r\n0\r\n\r\n"))
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(200)
     self.assertBody("I am a\nrequest body")
Example #45
0
 def test_request_payload_readline(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo_lines")
     body = ntob("I am a\nrequest body")
     c.putheader("Content-Length", len(body))
     c.endheaders()
     c.send(body)
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(200)
     self.assertBody(body)
Example #46
0
 def test_request_payload_readline(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo_lines")
     body = ntob("I am a\nrequest body")
     c.putheader("Content-Length", len(body))
     c.endheaders()
     c.send(body)
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(200)
     self.assertBody(body)
Example #47
0
 def test_no_content_length(self):
     # "The presence of a message-body in a request is signaled by the
     # inclusion of a Content-Length or Transfer-Encoding header field in
     # the request's message-headers."
     #
     # Send a message with neither header and no body.
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.request("POST", "/no_body")
     response = c.getresponse()
     self.body = response.fp.read()
     self.status = str(response.status)
     self.assertStatus(200)
     self.assertBody(ntob('Hello world!'))
Example #48
0
 def test_no_content_length(self):
     # "The presence of a message-body in a request is signaled by the
     # inclusion of a Content-Length or Transfer-Encoding header field in
     # the request's message-headers."
     # 
     # Send a message with neither header and no body.
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.request("POST", "/no_body")
     response = c.getresponse()
     self.body = response.fp.read()
     self.status = str(response.status)
     self.assertStatus(200)
     self.assertBody(ntob('Hello world!'))
Example #49
0
 def test_max_body(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo")
     body = ntob("x" * 1001)
     c.putheader("Content-Length", len(body))
     c.endheaders()
     c.send(body)
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(413)
     self.assertBody("The entity sent with the request exceeds "
                     "the maximum allowed bytes.")
Example #50
0
 def test_malformed_header(self):
     if self.scheme == 'https':
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest('GET', '/')
     c.putheader('Content-Type', 'text/plain')
     # See http://www.cherrypy.org/ticket/941 
     c._output(ntob('Re, 1.2.3.4#015#012'))
     c.endheaders()
     
     response = c.getresponse()
     self.status = str(response.status)
     self.assertStatus(400)
     self.body = response.fp.read(20)
     self.assertBody("Illegal header line.")
Example #51
0
    def test_malformed_header(self):
        if self.scheme == 'https':
            c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
        else:
            c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
        c.putrequest('GET', '/')
        c.putheader('Content-Type', 'text/plain')
        # See http://www.cherrypy.org/ticket/941
        c._output(ntob('Re, 1.2.3.4#015#012'))
        c.endheaders()

        response = c.getresponse()
        self.status = str(response.status)
        self.assertStatus(400)
        self.body = response.fp.read(20)
        self.assertBody("Illegal header line.")
Example #52
0
 def test_max_body(self):
     if self.scheme == "https":
         c = HTTPSConnection('%s:%s' % (self.interface(), self.PORT))
     else:
         c = HTTPConnection('%s:%s' % (self.interface(), self.PORT))
     c.putrequest("POST", "/echo")
     body = ntob("x" * 1001)
     c.putheader("Content-Length", len(body))
     c.endheaders()
     c.send(body)
     response = c.getresponse()
     self.status, self.headers, self.body = webtest.shb(response)
     c.close()
     self.assertStatus(413)
     self.assertBody(
         "The entity sent with the request exceeds "
         "the maximum allowed bytes.")
Example #53
0
    def test_598(self):
        remote_data_conn = urlopen('%s://%s:%s/one_megabyte_of_a/' %
                                   (self.scheme, self.HOST, self.PORT,))
        buf = remote_data_conn.read(512)
        time.sleep(timeout * 0.6)
        remaining = (1024 * 1024) - 512
        while remaining:
            data = remote_data_conn.read(remaining)
            if not data:
                break
            else:
                buf += data
            remaining -= len(data)

        self.assertEqual(len(buf), 1024 * 1024)
        self.assertEqual(buf, ntob('a' * 1024 * 1024))
        self.assertEqual(remaining, 0)
        remote_data_conn.close()
Example #54
0
            def echo_lines(self, req, resp):
                f = req.environ['wsgi.input']

                output = []
                while True:
                    line = f.readline().decode("ISO-8859-1")
                    if not line:
                        break
                    output.append(line)

                if hasattr(f, 'read_trailer_lines'):
                    for line in f.read_trailer_lines():
                        k, v = line.split(ntob(":"), 1)
                        k = tonative(k.strip())
                        v = tonative(v.strip())
                        resp.headers[k] = v

                return output
Example #55
0
    def test_598(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"
        remote_data_conn = urlopen('%s://%s:%s/one_megabyte_of_a' %
                                   (self.scheme, self.HOST, self.PORT))
        buf = remote_data_conn.read(512)
        time.sleep(timeout * 0.6)
        remaining = (1024 * 1024) - 512
        while remaining:
            data = remote_data_conn.read(remaining)
            if not data:
                break
            else:
                buf += data
            remaining -= len(data)

        self.assertEqual(len(buf), 1024 * 1024)
        self.assertEqual(buf, ntob("a" * 1024 * 1024))
        self.assertEqual(remaining, 0)
        remote_data_conn.close()
Example #56
0
    def test_HTTP11_Timeout(self):
        # If we timeout without sending any data,
        # the server will close the conn with a 408.
        if cherrypy.server.protocol_version != 'HTTP/1.1':
            return self.skip()

        self.PROTOCOL = 'HTTP/1.1'

        # Connect but send nothing.
        self.persistent = True
        conn = self.HTTP_CONN
        conn.auto_open = False
        conn.connect()

        # Wait for our socket timeout
        time.sleep(timeout * 2)

        # The request should have returned 408 already.
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.assertEqual(response.status, 408)
        conn.close()

        # Connect but send half the headers only.
        self.persistent = True
        conn = self.HTTP_CONN
        conn.auto_open = False
        conn.connect()
        conn.send(ntob('GET /hello HTTP/1.1'))
        conn.send(('Host: %s' % self.HOST).encode('ascii'))

        # Wait for our socket timeout
        time.sleep(timeout * 2)

        # The conn should have already sent 408.
        response = conn.response_class(conn.sock, method='GET')
        response.begin()
        self.assertEqual(response.status, 408)
        conn.close()
Example #57
0
 def test_normal_request(self):
     self.getPage("/hello")
     self.assertStatus(200)
     self.assertBody(ntob('Hello world!'))
Example #58
0
    def test_readall_or_close(self):
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        if self.scheme == "https":
            self.HTTP_CONN = HTTPSConnection
        else:
            self.HTTP_CONN = HTTPConnection

        # Test a max of 0 (the default) and then reset to what it was above.
        old_max = self.httpserver.max_request_body_size
        for new_max in (0, old_max):
            self.httpserver.max_request_body_size = new_max

            self.persistent = True
            conn = self.HTTP_CONN

            # Get a POST page with an error
            conn.putrequest("POST", "/err_before_read", skip_host=True)
            conn.putheader("Host", self.HOST)
            conn.putheader("Content-Type", "text/plain")
            conn.putheader("Content-Length", "1000")
            conn.putheader("Expect", "100-continue")
            conn.endheaders()
            response = conn.response_class(conn.sock, method="POST")

            # ...assert and then skip the 100 response
            version, status, reason = response._read_status()
            self.assertEqual(status, 100)
            while True:
                skip = response.fp.readline().strip()
                if not skip:
                    break

            # ...send the body
            conn.send(ntob("x" * 1000))

            # ...get the final response
            response.begin()
            self.status, self.headers, self.body = webtest.shb(response)
            self.assertStatus(500)

            # Now try a working page with an Expect header...
            conn._output(ntob('POST /upload HTTP/1.1'))
            conn._output(ntob("Host: %s" % self.HOST, 'ascii'))
            conn._output(ntob("Content-Type: text/plain"))
            conn._output(ntob("Content-Length: 17"))
            conn._output(ntob("Expect: 100-continue"))
            conn._send_output()
            response = conn.response_class(conn.sock, method="POST")

            # ...assert and then skip the 100 response
            version, status, reason = response._read_status()
            self.assertEqual(status, 100)
            while True:
                skip = response.fp.readline().strip()
                if not skip:
                    break

            # ...send the body
            body = ntob("I am a small file")
            conn.send(body)

            # ...get the final response
            response.begin()
            self.status, self.headers, self.body = webtest.shb(response)
            self.assertStatus(200)
            self.assertBody("thanks for '%s'" % body)
            conn.close()
Example #59
0
    def test_HTTP11_Timeout_after_request(self):
        # If we timeout after at least one request has succeeded,
        # the server will close the conn without 408.
        self.httpserver.protocol = "HTTP/1.1"
        self.PROTOCOL = "HTTP/1.1"

        # Make an initial request
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest("GET", "/timeout?t=%s" % timeout, skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)
        self.body = response.read()
        self.assertBody(str(timeout))

        # Make a second request on the same socket
        conn._output(ntob('GET /hello HTTP/1.1'))
        conn._output(ntob("Host: %s" % self.HOST, 'ascii'))
        conn._send_output()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)
        self.body = response.read()
        self.assertBody("Hello, world!")

        # Wait for our socket timeout
        time.sleep(timeout * 2)

        # Make another request on the same socket, which should error
        conn._output(ntob('GET /hello HTTP/1.1'))
        conn._output(ntob("Host: %s" % self.HOST, 'ascii'))
        conn._send_output()
        response = conn.response_class(conn.sock, method="GET")
        try:
            response.begin()
        except:
            if not isinstance(sys.exc_info()[1],
                              (socket.error, BadStatusLine)):
                self.fail("Writing to timed out socket didn't fail"
                          " as it should have: %s" % sys.exc_info()[1])
        else:
            if response.status != 408:
                self.fail("Writing to timed out socket didn't fail"
                          " as it should have: %s" %
                          response.read())

        conn.close()

        # Make another request on a new socket, which should work
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest("GET", "/pov", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)
        self.body = response.read()
        self.assertBody(pov)


        # Make another request on the same socket,
        # but timeout on the headers
        conn.send(ntob('GET /hello HTTP/1.1'))
        # Wait for our socket timeout
        time.sleep(timeout * 2)
        response = conn.response_class(conn.sock, method="GET")
        try:
            response.begin()
        except:
            if not isinstance(sys.exc_info()[1],
                              (socket.error, BadStatusLine)):
                self.fail("Writing to timed out socket didn't fail"
                          " as it should have: %s" % sys.exc_info()[1])
        else:
            self.fail("Writing to timed out socket didn't fail"
                      " as it should have: %s" %
                      response.read())

        conn.close()

        # Retry the request on a new connection, which should work
        self.persistent = True
        conn = self.HTTP_CONN
        conn.putrequest("GET", "/pov", skip_host=True)
        conn.putheader("Host", self.HOST)
        conn.endheaders()
        response = conn.response_class(conn.sock, method="GET")
        response.begin()
        self.assertEqual(response.status, 200)
        self.body = response.read()
        self.assertBody(pov)
        conn.close()