예제 #1
0
    def testOnlyHandleAMaximumNrOfRequests(self):
        codes = []
        def handler(**kwargs):
            yield "OK"

        def error_handler(**kwargs):
            codes.append(kwargs['ResponseCode'])
            yield "FAIL"

        server = HttpServer(self.reactor, self.port, handler, errorHandler=error_handler, maxConnections=5)
        server.listen()

        self.reactor.getOpenConnections = lambda: 10

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()
        server.shutdown()

        self.assertEquals('FAIL', sock.recv(1024))
        self.assertEquals([503], codes)

        # cleanup
        sock.close()
예제 #2
0
    def testYieldInHttpServer(self):
        bucket = []
        def handler(RequestURI, **kwargs):
            yield 'A'
            while 'continue' not in bucket:
                yield Yield
            yield 'B'

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send('GET /path/here HTTP/1.0\r\n\r\n')
                for i in xrange(500):
                    reactor.step()
                self.assertEquals('A', sok.recv(100))
                bucket.append('continue')
                reactor.step()
                self.assertEquals('B', sok.recv(100))

                # cleanup
                sok.close()
                server.shutdown()
예제 #3
0
    def testOnlyHandleAMaximumNrOfRequests(self):
        codes = []

        def handler(**kwargs):
            yield "OK"

        def error_handler(**kwargs):
            codes.append(kwargs['ResponseCode'])
            yield "FAIL"

        server = HttpServer(self.reactor,
                            self.port,
                            handler,
                            errorHandler=error_handler,
                            maxConnections=5)
        server.listen()

        self.reactor.getOpenConnections = lambda: 10

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()
        server.shutdown()

        self.assertEquals('FAIL', sock.recv(1024))
        self.assertEquals([503], codes)
예제 #4
0
    def sendRequestAndReceiveResponse(self, request, response='The Response', recvSize=4096, compressResponse=False, extraStepAfterCompress=True):
        self.responseCalled = False
        @compose
        def responseGenFunc(**kwargs):
            yield response
            yield ''
            self.responseCalled = True
        server = HttpServer(self.reactor, self.port, responseGenFunc, recvSize=recvSize, compressResponse=compressResponse)
        server.listen()
        sok = socket()
        sok.connect(('localhost', self.port))
        sok.send(request)

        mockStdout = None
        with self.stdout_replaced() as mockStdout:
            while not self.responseCalled:
                self.reactor.step()
            if compressResponse and extraStepAfterCompress: #not everythingSent???: 
                self.reactor.step()
        stdoutValue = mockStdout.getvalue()
        if stdoutValue:
            print stdoutValue

        server.shutdown()
        r = sok.recv(4096)
        sok.close()
        return r
예제 #5
0
    def testReadMultipartFormEndBoundary(self):
        httpRequest = open(inmydir('data/multipart-data-04')).read()
        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send(httpRequest)

                reactor.addTimer(2, lambda: self.fail("Test Stuck"))
                while self.requestData.get('Form', None) == None:
                    reactor.step()
                form = self.requestData['Form']
                self.assertEquals(1, len(form))
                self.assertEquals(3521*'X', form['id'][0])

                # cleanup
                sok.close()
                server.shutdown()
예제 #6
0
    def testTextFileSeenAsFile(self):
        httpRequest = open(inmydir('data/multipart-data-03')).read()
        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send(httpRequest)

                reactor.addTimer(2, lambda: self.fail("Test Stuck"))
                while self.requestData.get('Form', None) == None:
                    reactor.step()
                form = self.requestData['Form']
                self.assertEquals(4, len(form))
                self.assertEquals(['SOME ID'], form['id'])
                self.assertEquals(1, len(form['somename']))
                filename, mimetype, data = form['somename'][0]
                self.assertEquals('hello.bas', filename)
                self.assertEquals('text/plain', mimetype)

                # cleanup
                sok.close()
                server.shutdown()
예제 #7
0
    def testPostMethodDeCompressesDeflatedBody_deflate(self):
        self.requestData = None
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler, timeout=0.01)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                bodyData = 'bodydatabodydata'
                bodyDataCompressed = compress(bodyData)
                contentLengthCompressed = len(bodyDataCompressed)
                sok.send(('POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nContent-Encoding: deflate\r\n\r\n' % contentLengthCompressed) + bodyDataCompressed)

                while not self.requestData:
                    reactor.step()
                self.assertEquals(dict, type(self.requestData))
                self.assertTrue('Headers' in self.requestData)
                headers = self.requestData['Headers']
                self.assertEquals('POST', self.requestData['Method'])
                self.assertEquals('application/x-www-form-urlencoded', headers['Content-Type'])
                self.assertEquals(contentLengthCompressed, int(headers['Content-Length']))  # TS: is this correct?, maybe decompressed length?

                self.assertTrue('Body' in self.requestData)
                self.assertEquals('bodydatabodydata', self.requestData['Body'])

                # cleanup
                sok.close()
                server.shutdown()
예제 #8
0
    def testPostMethodDeCompressesDeflatedBody_unrecognizedEncoding(self):
        self.requestData = None
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, handler, timeout=0.01)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            bodyData = 'bodydatabodydata'
            bodyDataCompressed = compress(bodyData)
            contentLengthCompressed = len(bodyDataCompressed)
            sok.send(('POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nContent-Encoding: unknown\r\n\r\n' % contentLengthCompressed) + bodyDataCompressed)

            while select([sok],[], [], 0) != ([sok], [], []):
                reactor.step()
            self.assertTrue(sok.recv(4096).startswith('HTTP/1.0 400 Bad Request'))

            self.assertEquals(None, self.requestData)

            # cleanup
            sok.close()
            server.shutdown()
예제 #9
0
    def testReadChunkedAndCompressedPost(self):
        postData = 'AhjBeehCeehAhjBeehCeehAhjBeehCeehAhjBeehCeeh'
        postDataCompressed = compress(postData)
        self.assertEquals(20, len(postDataCompressed))
        self.assertEquals(15, len(postDataCompressed[:15]))
        self.assertEquals(5, len(postDataCompressed[15:]))

        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler, timeout=0.01, recvSize=3)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                postString = 'POST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nTransfer-Encoding: chunked\r\nContent-Encoding: deflate\r\n\r\nf\r\n%s\r\n5\r\n%s\r\n0\r\n' % (postDataCompressed[:15], postDataCompressed[15:])
                sok.send(postString)

                reactor.addTimer(0.2, lambda: self.fail("Test Stuck"))
                while self.requestData.get('Body', None) != postData:
                    reactor.step()

                # cleanup
                sok.close()
                server.shutdown()
예제 #10
0
    def testPutMethodReadsBody(self):
        self.requestData = None
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler, timeout=0.01)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send('PUT / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 8\r\n\r\nbodydata')

                while not self.requestData:
                    reactor.step()
                self.assertEquals(dict, type(self.requestData))
                self.assertTrue('Headers' in self.requestData)
                headers = self.requestData['Headers']
                self.assertEquals('PUT', self.requestData['Method'])
                self.assertEquals('application/x-www-form-urlencoded', headers['Content-Type'])
                self.assertEquals(8, int(headers['Content-Length']))

                self.assertTrue('Body' in self.requestData)
                self.assertEquals('bodydata', self.requestData['Body'])

                # cleanup
                sok.close()
                server.shutdown()
예제 #11
0
    def testInvalidPOSTRequestStartsOnlyOneTimer(self):
        # problem in found in OAS, timers not removed properly when whole body hasnt been read yet
        _httpserver.RECVSIZE = 1
        with Reactor() as reactor:
            timers = []
            orgAddTimer = reactor.addTimer
            def addTimerInterceptor(*timer):
                timers.append(timer)
                return orgAddTimer(*timer)
            reactor.addTimer = addTimerInterceptor
            server = HttpServer(reactor, self.port, lambda **kwargs: (x for x in []), timeout=0.01)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('POST / HTTP/1.0\r\nContent-Length: 10\r\n\r\n')
            reactor.step()
            sok.send(".")
            sleep(0.1)
            reactor.step()
            sok.send(".")
            reactor.step()
            sleep(0.1)
            while select([sok],[], [], 0) != ([sok], [], []):
                reactor.step()
            self.assertEquals(2, len(timers))

            # cleanup
            sok.close()
            server.shutdown()
예제 #12
0
    def XXX_testPostMultipartFormCompressed(self):
        """Not yet"""
        httpRequest = open(inmydir('data/multipart-data-01-compressed')).read()
        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, handler)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send(httpRequest)

            reactor.addTimer(2, lambda: self.fail("Test Stuck"))
            while self.requestData.get('Form', None) == None:
                reactor.step()
            form = self.requestData['Form']
            self.assertEquals(4, len(form))
            self.assertEquals(['SOME ID'], form['id'])

            # cleanup
            sok.close()
            server.shutdown()
예제 #13
0
    def testWindowsPostMultipartForm(self):
        httpRequest = open(inmydir('data/multipart-data-02')).read()
        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send(httpRequest)

                reactor.addTimer(2, lambda: self.fail("Test Stuck"))
                while self.requestData.get('Form', None) == None:
                    reactor.step()
                form = self.requestData['Form']
                self.assertEquals(4, len(form))
                self.assertEquals(['SOME ID'], form['id'])
                self.assertEquals(1, len(form['somename']))
                filename, mimetype, data = form['somename'][0]
                self.assertEquals('Bank Gothic Medium BT.ttf', filename)
                self.assertEquals('application/octet-stream', mimetype)

                # cleanup
                sok.close()
                server.shutdown()
예제 #14
0
    def testHttpServerEncodesUnicode(self):
        unicodeString = u'some t\xe9xt'
        oneStringLength = len(unicodeString.encode(getdefaultencoding()))
        self.assertTrue(len(unicodeString) != oneStringLength)
        def response(**kwargs):
            yield unicodeString * 6000

        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, response, recvSize=3)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('GET /path/here HTTP/1.0\r\nConnection: close\r\nApe-Nut: Mies\r\n\r\n')
            writers = lambda: [c for c in reactor._fds.values() if c.intent == WRITE_INTENT]
            while not writers():
                reactor.step()
            reactor.step()
            reactor.step()
            fragment = sok.recv(100000) # will read about 49152 chars
            self.assertEquals(oneStringLength * 6000, len(fragment))
            self.assertTrue("some t\xc3\xa9xt" in fragment, fragment)

            # cleanup
            sok.close()
            server.shutdown()
예제 #15
0
    def testSmallFragmentsWhileSendingResponse(self):
        def response(**kwargs):
            yield ''            # Socket poking here - then try to really send stuff
            yield 'some text that is longer than '
            yield 'the lenght of fragments sent'

        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, response, recvSize=3)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('GET /path/here HTTP/1.0\r\nConnection: close\r\nApe-Nut: Mies\r\n\r\n')
            writerFile = lambda: [context.fileOrFd for context in reactor._fds.values() if context.intent == WRITE_INTENT]
            while not writerFile():
                reactor.step()
            serverSok = writerFile()[0]
            originalSend = serverSok.send
            def sendOnlyManagesToActuallySendThreeBytesPerSendCall(data, *options):
                originalSend(data[:3], *options)
                return 3
            serverSok.send = sendOnlyManagesToActuallySendThreeBytesPerSendCall
            for i in range(22):
                reactor.step()
            fragment = sok.recv(4096)
            self.assertEquals('some text that is longer than the lenght of fragments sent', fragment)

            # cleanup
            sok.close()
            server.shutdown()
예제 #16
0
    def testPostMethodTimesOutOnBadBody(self):
        self.requestData = None
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        done = []
        def onDone():
            fromServer = sok.recv(1024)
            self.assertTrue('HTTP/1.0 400 Bad Request' in fromServer)
            done.append(True)

        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, handler, timeout=0.01)
            server.listen()
            reactor.addTimer(0.02, onDone)
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 8\r\n\r\n')

            while not done:
                reactor.step()

            # cleanup
            sok.close()
            server.shutdown()
예제 #17
0
    def testConnectBindAddress(self):
        reactor = CallTrace()
        server = HttpServer(reactor, self.port, lambda **kwargs: None, bindAddress='127.0.0.1')
        server.listen()
        self.assertEquals(('127.0.0.1', self.port), server._acceptor._sok.getsockname())

        # cleanup
        server.shutdown()
예제 #18
0
class AsyncReaderTest(WeightlessTestCase):

    def dispatch(self, *args, **kwargs):
        return compose(self.handler(*args, **kwargs))

    def setUp(self):
        WeightlessTestCase.setUp(self)
        self.reactor = Reactor()
        self.port = randint(2**10, 2**16)
        self.httpserver = HttpServer(self.reactor, self.port, self.dispatch)
        self.httpserver.listen()

    def tearDown(self):
        self.httpserver.shutdown()
        self.reactor.shutdown()
        WeightlessTestCase.tearDown(self)

    def testHttpRequest(self):
        self.assertEquals('GET / HTTP/1.0\r\n', _httpRequest('GET', '/'))
        self.assertEquals('POST / HTTP/1.0\r\n', _httpRequest('POST', '/'))

    def testPassRequestThruToBackOfficeServer(self):
        done = [False]
        backofficeport = self.port + 1
        def passthruhandler(*args, **kwargs):
            request = kwargs['RequestURI']
            response = yield httpget('localhost', backofficeport, request)
            yield response
            done[0] = True
        self.handler = passthruhandler
        expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n"
        responses = (i for i in ['hel', 'lo!'])
        backofficeserver = testserver(backofficeport, responses, expectedrequest)
        client = clientget('localhost', self.port, '/depot?arg=1&arg=2')
        while not done[0]:
            self.reactor.step()
        response = client.recv(99)
        self.assertEquals('hello!', response)

    def testConnectFails(self):
        exceptions = []
        def failingserver(*args, **kwarg):
            try:
                response = yield httpget(*target)
            except Exception, e:
                exceptions.append(exc_info())
        self.handler = failingserver

        clientget('localhost', self.port, '/')
        target = ('localhost', 'port', '/') # non-numeric port
        try:
            with self.stderr_replaced():
                with self.loopingReactor():
                    while not exceptions:
                        pass
        except Exception, e:
            pass
예제 #19
0
    def testValidRequestResetsTimer(self):
        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, lambda **kwargs: ('a' for a in range(3)), timeout=0.01, recvSize=3)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('GET / HTTP/1.0\r\n\r\n')
            sleep(0.02)
            for i in range(11):
                reactor.step()
            response = sok.recv(4096)
            self.assertEquals('aaa', response)

            # cleanup
            sok.close()
            server.shutdown()
예제 #20
0
    def testDefaultErrorHandler(self):
        def handler(**kwargs):
            yield "OK"

        server = HttpServer(self.reactor, self.port, handler, maxConnections=5)
        server.listen()

        self.reactor.getOpenConnections = lambda: 10

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()

        self.assertEquals('HTTP/1.0 503 Service Unavailable\r\n\r\n<html><head></head><body><h1>Service Unavailable</h1></body></html>', sock.recv(1024))
        server.shutdown()
예제 #21
0
    def testInvalidRequestWithHalfHeader(self):
        with Reactor() as reactor:
            server = HttpServer(reactor, self.port, None, timeout=0.1)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('POST / HTTP/1.0\r\n')
            sok.send('Expect: something\r\n')
            sok.send('Content-Length: 5\r\n')
            sok.send('\r\n1234')
            sok.close()
            with self.stderr_replaced() as s:
                for i in range(4):
                    reactor.step()
                self.assertEquals(1, len([c for c in reactor._fds.values() if c.intent == READ_INTENT]))

            # cleanup
            sok.close()
            server.shutdown()
예제 #22
0
    def testDefaultErrorHandler(self):
        def handler(**kwargs):
            yield "OK"

        server = HttpServer(self.reactor, self.port, handler, maxConnections=5)
        server.listen()

        self.reactor.getOpenConnections = lambda: 10

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()

        self.assertEquals(
            'HTTP/1.0 503 Service Unavailable\r\n\r\n<html><head></head><body><h1>Service Unavailable</h1></body></html>',
            sock.recv(1024))
        server.shutdown()
예제 #23
0
    def testSendHeader(self):
        self.kwargs = None
        def response(**kwargs):
            self.kwargs = kwargs
            yield 'nosense'

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, response)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send('GET /path/here HTTP/1.0\r\nConnection: close\r\nApe-Nut: Mies\r\n\r\n')
                while not self.kwargs:
                    reactor.step()
                self.assertEquals({'Body': '', 'RequestURI': '/path/here', 'HTTPVersion': '1.0', 'Method': 'GET', 'Headers': {'Connection': 'close', 'Ape-Nut': 'Mies'}, 'Client': ('127.0.0.1', MATCHALL)}, self.kwargs)

                # cleanup
                sok.close()
                server.shutdown()
예제 #24
0
    def testOnlyHandleAMaximumNrOfRequestsBelowBoundary(self):
        def handler(**kwargs):
            yield "OK"

        def error_handler(**kwargs):
            yield "FAIL"

        server = HttpServer(self.reactor, self.port, handler, errorHandler=error_handler, maxConnections=10)
        server.listen()

        self.reactor.getOpenConnections = lambda: 5

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()
        server.shutdown()

        self.assertEquals('OK', sock.recv(1024))
예제 #25
0
    def testConnect(self):
        self.req = False
        def onRequest(**kwargs):
            self.req = True
            yield 'nosens'

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, onRequest)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send('GET / HTTP/1.0\r\n\r\n')
                reactor.step() # connect/accept
                reactor.step() # read GET request
                reactor.step() # call onRequest for response data
                self.assertEquals(True, self.req)

                # cleanup
                server.shutdown()
                sok.close()
예제 #26
0
    def testHandlerExitsWithException(self):
        exceptions = []
        exc_message = "this is not an I/O exception, but an application exception"
        yielded_data = "a bit of data"
        def handler(**kwargs):
            yield yielded_data
            raise Exception(exc_message)
            yield
        server = HttpServer(self.reactor, self.port, handler, maxConnections=5)
        server.listen()
        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step()
        with stderr_replaced() as f:
            self.reactor.step().step()
            self.assertFalse(yielded_data in f.getvalue())
            self.assertTrue("Exception: %s" % exc_message in f.getvalue())

        server.shutdown()
        sock.close()
예제 #27
0
    def testReadChunkedPost(self):
        self.requestData = {}
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler, timeout=0.01, recvSize=3)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                sok.send('POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nabcde\r\n5\r\nfghij\r\n0\r\n')

                reactor.addTimer(0.2, lambda: self.fail("Test Stuck"))
                while self.requestData.get('Body', None) != 'abcdefghij':
                    reactor.step()

                # cleanup
                sok.close()
                server.shutdown()
예제 #28
0
    def sendRequestAndReceiveResponse(self,
                                      request,
                                      response='The Response',
                                      recvSize=4096,
                                      compressResponse=False,
                                      extraStepAfterCompress=True):
        self.responseCalled = False

        @compose
        def responseGenFunc(**kwargs):
            yield response
            yield ''
            self.responseCalled = True

        server = HttpServer(self.reactor,
                            self.port,
                            responseGenFunc,
                            recvSize=recvSize,
                            compressResponse=compressResponse)
        server.listen()
        sok = socket()
        sok.connect(('localhost', self.port))
        sok.send(request)

        mockStdout = None
        with self.stdout_replaced() as mockStdout:
            while not self.responseCalled:
                self.reactor.step()
            if compressResponse and extraStepAfterCompress:  #not everythingSent???:
                self.reactor.step()
        stdoutValue = mockStdout.getvalue()
        if stdoutValue:
            print stdoutValue

        server.shutdown()
        r = sok.recv(4096)
        sok.close()
        return r
예제 #29
0
    def testInvalidGETRequestStartsOnlyOneTimer(self):
        _httpserver.RECVSIZE = 3
        with Reactor() as reactor:
            timers = []
            orgAddTimer = reactor.addTimer
            def addTimerInterceptor(*timer):
                timers.append(timer)
                return orgAddTimer(*timer)
            reactor.addTimer = addTimerInterceptor
            server = HttpServer(reactor, self.port, None, timeout=0.01)
            server.listen()
            sok = socket()
            sok.connect(('localhost', self.port))
            sok.send('GET HTTP/1.0\r\n\r\n') # no path
            while select([sok],[], [], 0) != ([sok], [], []):
                reactor.step()
            response = sok.recv(4096)
            self.assertEquals('HTTP/1.0 400 Bad Request\r\n\r\n', response)
            self.assertEquals(1, len(timers))

            # cleanup
            sok.close()
            server.shutdown()
예제 #30
0
    def testOnlyHandleAMaximumNrOfRequestsBelowBoundary(self):
        def handler(**kwargs):
            yield "OK"

        def error_handler(**kwargs):
            yield "FAIL"

        server = HttpServer(self.reactor,
                            self.port,
                            handler,
                            errorHandler=error_handler,
                            maxConnections=10)
        server.listen()

        self.reactor.getOpenConnections = lambda: 5

        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        self.reactor.step().step().step()
        server.shutdown()

        self.assertEquals('OK', sock.recv(1024))
예제 #31
0
    def testPostMethodDeCompressesDeflatedBody_gzip(self):
        self.requestData = None
        def handler(**kwargs):
            self.requestData = kwargs
            return
            yield

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler, timeout=0.01)
                server.listen()
                sok = socket()
                sok.connect(('localhost', self.port))
                bodyData = 'bodydatabodydata'
                _sio = StringIO()
                _gzFileObj = GzipFile(filename=None, mode='wb', compresslevel=6, fileobj=_sio)
                _gzFileObj.write(bodyData); _gzFileObj.close()
                bodyDataCompressed = _sio.getvalue()
                contentLengthCompressed = len(bodyDataCompressed)
                sok.send(('POST / HTTP/1.0\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\nContent-Encoding: gzip\r\n\r\n' % contentLengthCompressed) + bodyDataCompressed)

                while not self.requestData:
                    reactor.step()
                self.assertEquals(dict, type(self.requestData))
                self.assertTrue('Headers' in self.requestData)
                headers = self.requestData['Headers']
                self.assertEquals('POST', self.requestData['Method'])
                self.assertEquals('application/x-www-form-urlencoded', headers['Content-Type'])
                self.assertEquals(contentLengthCompressed, int(headers['Content-Length']))

                self.assertTrue('Body' in self.requestData)
                self.assertEquals('bodydatabodydata', self.requestData['Body'])

                # cleanup
                sok.close()
                server.shutdown()
예제 #32
0
    def testYieldPossibleUseCase(self):
        bucket = []
        result = []
        ready = []
        useYield = []
        workDone = []
        def handler(RequestURI, **kwargs):
            name = 'work' if 'aLotOfWork' in RequestURI else 'lazy'
            bucket.append('%s_START' % name)
            yield 'START'
            if '/aLotOfWork' in RequestURI:
                bucket.append('%s_part_1' % name)
                if True in useYield:
                    while not workDone:
                        yield Yield
                bucket.append('%s_part_2' % name)
            bucket.append('%s_END' % name)
            ready.append('yes')
            yield 'END'

        with stdout_replaced():
            with Reactor() as reactor:
                server = HttpServer(reactor, self.port, handler)
                server.listen()

                def loopWithYield(use):
                    del ready[:]
                    del bucket[:]
                    del result[:]
                    del workDone[:]
                    useYield[:] = [use]
                    sok0 = socket()
                    sok0.connect(('localhost', self.port))
                    sok0.send('GET /aLotOfWork HTTP/1.0\r\n\r\n')
                    sok1 = socket()
                    sok1.connect(('localhost', self.port))
                    sok1.send('GET /path/here HTTP/1.0\r\n\r\n')
                    sleep(0.02)
                    while ready != ['yes']:
                        reactor.step()
                        if bucket:
                            result.append(set(bucket))
                            del bucket[:]
                    workDone.append(True)
                    while ready != ['yes', 'yes']:
                        reactor.step()
                        if bucket:
                            result.append(set(bucket))
                            del bucket[:]

                    sok0.close()
                    sok1.close()
                    return result

                self.assertEquals([
                        set(['work_START']),
                        set(['lazy_START', 'work_part_1', 'work_part_2', 'work_END']),
                        set(['lazy_END'])
                   ], loopWithYield(False))
                self.assertEquals([
                        set(['work_START']),
                        set(['lazy_START', 'work_part_1']),
                        set(['lazy_END']),
                        set(['work_part_2', 'work_END']),
                   ], loopWithYield(True))

                # cleanup
                server.shutdown()
class ObservableHttpServer(Observable):
    def __init__(self,
                 reactor,
                 port,
                 timeout=1,
                 prio=None,
                 sok=None,
                 maxConnections=None,
                 compressResponse=True,
                 bindAddress=None):
        Observable.__init__(self)
        self._port = port
        self._reactor = reactor
        self._timeout = timeout
        self._started = False
        self._prio = prio
        self._sok = sok
        self._maxConnections = maxConnections
        self._compressResponse = compressResponse
        self._bindAddress = bindAddress

    def startServer(self):
        """Starts server,

        When running a http server on port 80, this method should be called by the
        root user. In other cases it will be started when initializing all observers,
        see observer_init()
        """
        self._httpserver = HttpServer(self._reactor,
                                      self._port,
                                      self._connect,
                                      timeout=self._timeout,
                                      prio=self._prio,
                                      sok=self._sok,
                                      maxConnections=self._maxConnections,
                                      errorHandler=self._error,
                                      compressResponse=self._compressResponse,
                                      bindAddress=self._bindAddress)
        self._httpserver.listen()
        self._started = True

    def observer_init(self):
        if not self._started:
            self.startServer()

    def _connect(self, **kwargs):
        return compose(self.handleRequest(port=self._port, **kwargs))

    def _error(self, **kwargs):
        yield serverUnavailableHtml +\
        '<html><head></head><body><h1>Service Unavailable</h1></body></html>'
        self.do.logHttpError(**kwargs)

    def handleRequest(self, RequestURI=None, **kwargs):
        scheme, netloc, path, query, fragments = urlsplit(RequestURI)
        arguments = parse_qs(str(query, encoding="utf-8"),
                             keep_blank_values=True)
        requestArguments = {
            'scheme': scheme,
            'netloc': netloc,
            'path': path,
            'query': query,
            'fragments': fragments,
            'arguments': arguments,
            'RequestURI': RequestURI
        }
        requestArguments.update(kwargs)
        savedBody = None
        if 'Body' in requestArguments:
            savedBody = requestArguments.pop('Body')
        convertedResult = _convertToStrings(requestArguments)
        if not savedBody is None:
            convertedResult['Body'] = savedBody

        yield self.all.handleRequest(**convertedResult)

    def setMaxConnections(self, m):
        self._httpserver.setMaxConnections(m)

    def shutdown(self):
        self._httpserver.shutdown()
예제 #34
0
class AsyncReaderTest(WeightlessTestCase):
    def setUp(self):
        WeightlessTestCase.setUp(self)
        self.port = PortNumberGenerator.next()
        self.httpserver = HttpServer(self.reactor, self.port, self._dispatch)
        self.httpserver.listen()

    def tearDown(self):
        self.httpserver.shutdown()
        WeightlessTestCase.tearDown(self)

    def testRequestLine(self):
        self.assertEquals('GET / HTTP/1.0\r\n', _requestLine('GET', '/'))
        self.assertEquals('POST / HTTP/1.0\r\n', _requestLine('POST', '/'))

    def testEmptyRequestConvenientlyTranslatedToSlash(self):
        self.assertEquals('GET / HTTP/1.0\r\n', _requestLine('GET', ''))
        self.assertEquals('POST / HTTP/1.0\r\n', _requestLine('POST', ''))

    def testPassRequestThruToBackOfficeServer(self):
        backofficeport = PortNumberGenerator.next()

        def passthruhandler(*args, **kwargs):
            request = kwargs['RequestURI']
            response = yield httpget('localhost', backofficeport, request)
            yield response

        self.handler = passthruhandler
        expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n"
        responses = (i for i in ['hel', 'lo!'])
        backofficeserver = testserver(backofficeport, responses,
                                      expectedrequest)
        client = clientget('localhost', self.port, '/depot?arg=1&arg=2')
        self._loopReactorUntilDone()
        response = client.recv(99)
        self.assertEquals('hello!', response)

    def testPassRequestThruToBackOfficeServerWithHttpRequest(self):
        backofficeport = PortNumberGenerator.next()

        def passthruhandler(*args, **kwargs):
            request = kwargs['RequestURI']
            response = yield HttpRequest().httprequest(host='localhost',
                                                       port=backofficeport,
                                                       request=request)
            yield response

        self.handler = passthruhandler
        expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n"
        responses = (i for i in ['hel', 'lo!'])
        backofficeserver = testserver(backofficeport, responses,
                                      expectedrequest)
        client = clientget('localhost', self.port, '/depot?arg=1&arg=2')
        self._loopReactorUntilDone()
        response = client.recv(99)
        self.assertEquals('hello!', response)

    @stderr_replaced
    def testConnectFails(self):
        def failingserver(*args, **kwarg):
            response = yield httpget(*target)

        self.handler = failingserver

        clientget('localhost', self.port, '/')
        target = ('localhost', 'port', '/')  # non-numeric port
        self._loopReactorUntilDone()

        expectedTraceback = ignoreLineNumbers(
            """Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 85, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 78, in httprequest
    result = s.getResult()
  File "%(suspend.py)s", line 34, in __call__
    self._doNext(self)
  File "%(httprequest.py)s", line 35, in _do
    sok.connect((host, port))
  File "<string>", line 1, in connect
TypeError: an integer is required
       """ % fileDict)
        if PYVERSION == "2.7":
            expectedTraceback = ignoreLineNumbers(
                """Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 85, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 78, in httprequest
    result = s.getResult()
  File "%(suspend.py)s", line 34, in __call__
    self._doNext(self)
  File "%(httprequest.py)s", line 35, in _do
    sok.connect((host, port))
  File "/usr/lib/python2.7/socket.py", line [#], in meth
    return getattr(self._sock,name)(*args)
TypeError: an integer is required
       """ % fileDict)
        self.assertEquals(TypeError, self.error[0])
        self.assertEqualsWS(
            expectedTraceback,
            ignoreLineNumbers(''.join(format_exception(*self.error))))

        target = ('localhost', 87, '/')  # invalid port
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(IOError, self.error[0])

        target = ('UEYR^$*FD(#>NDJ.khfd9.(*njnd', PortNumberGenerator.next(),
                  '/')  # invalid host
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(SocketGaiError, self.error[0])

        target = ('127.0.0.1', PortNumberGenerator.next(), '/'
                  )  # No-one listens
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(IOError, self.error[0])
        self.assertEquals('111', str(self.error[1]))

    @stdout_replaced
    def testTracebackPreservedAcrossSuspend(self):
        backofficeport = PortNumberGenerator.next()
        expectedrequest = ''
        testserver(backofficeport, [], expectedrequest)
        target = ('localhost', backofficeport, '/')

        exceptions = []

        def failingserver(*args, **kwarg):
            response = yield httpget(*target)

        self.handler = failingserver

        def requestLine(self, *args, **kwargs):
            raise RuntimeError("Boom!")

        try:
            originalRequestLine = httpRequestModule._requestLine
            httpRequestModule._requestLine = requestLine

            clientget('localhost', self.port, '/')
            with stderr_replaced():
                self._loopReactorUntilDone()

            expectedTraceback = ignoreLineNumbers(
                """Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 192, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 129, in httprequest
    result = s.getResult()
  File "%(httprequest.py)s", line 83, in _do
    yield _sendHttpHeaders(sok, method, request, headers)
  File "%(httprequest.py)s", line 121, in _sendHttpHeaders
    data = _requestLine(method, request)
  File "%(__file__)s", line 198, in requestLine
    raise RuntimeError("Boom!")
RuntimeError: Boom!""" % fileDict)
            resultingTraceback = ''.join(format_exception(*self.error))
            self.assertEqualsWS(expectedTraceback,
                                ignoreLineNumbers(resultingTraceback))

        finally:
            httpRequestModule._requestLine = originalRequestLine

    def testHttpPost(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request)
        body = u"BÖDY" * 20000
        responses = []

        def posthandler(*args, **kwargs):
            response = yield httppost('localhost',
                                      port,
                                      '/path',
                                      body,
                                      headers={'Content-Type': 'text/plain'})
            yield response
            responses.append(response)

        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(
            ['Content-Length: 100000\r\n', 'Content-Type: text/plain\r\n'],
            headers)
        self.assertEquals(body, post_request[0]['body'])

    def testHttpPostWithoutHeaders(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request)
        body = u"BÖDY" * 20000
        responses = []

        def posthandler(*args, **kwargs):
            response = yield httppost('localhost', port, '/path', body)
            yield response
            responses.append(response)

        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(['Content-Length: 100000\r\n'], headers)
        self.assertEquals(body, post_request[0]['body'])

    def testHttpsPost(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request, ssl=True)
        body = u"BÖDY" * 20000
        responses = []

        def posthandler(*args, **kwargs):
            response = yield httpspost('localhost',
                                       port,
                                       '/path',
                                       body,
                                       headers={'Content-Type': 'text/plain'})
            yield response
            responses.append(response)

        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(
            ['Content-Length: 100000\r\n', 'Content-Type: text/plain\r\n'],
            headers)
        self.assertEquals(body, post_request[0]['body'])

    @stderr_replaced
    def testHttpsPostOnIncorrectPort(self):
        responses = []

        def posthandler(*args, **kwargs):
            response = yield httpspost('localhost',
                                       PortNumberGenerator.next(),
                                       '/path',
                                       "body",
                                       headers={'Content-Type': 'text/plain'})
            yield response
            responses.append(response)

        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue(self.error[0] is IOError)
        self.assertEquals("111", str(self.error[1]))

    def testHttpGet(self):
        get_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, get_request)

        responses = []

        def gethandler(*args, **kwargs):
            response = 'no response yet'
            try:
                response = yield httpget('localhost',
                                         port,
                                         '/path',
                                         headers={
                                             'Content-Type': 'text/plain',
                                             'Content-Length': 0
                                         },
                                         prio=4)
            finally:
                responses.append(response)
            yield 'HTTP/1.0 200 OK\r\n\r\n'

        self.handler = gethandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("GET RESPONSE" in responses[0], responses[0])
        self.assertEquals('GET', get_request[0]['command'])
        self.assertEquals('/path', get_request[0]['path'])
        headers = get_request[0]['headers'].headers
        self.assertEquals(
            ['Content-Length: 0\r\n', 'Content-Type: text/plain\r\n'], headers)

    def testHttpRequest(self):
        get_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, get_request)

        responses = []

        def gethandler(*args, **kwargs):
            response = 'no response yet'
            try:
                response = yield httprequest(method='MYMETHOD',
                                             host='localhost',
                                             port=port,
                                             request='/path',
                                             headers={
                                                 'Content-Type': 'text/plain',
                                                 'Content-Length': 0
                                             },
                                             prio=4)
            finally:
                responses.append(response)
            yield 'HTTP/1.0 200 OK\r\n\r\n'

        self.handler = gethandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue(
            "Message: Unsupported method ('MYMETHOD')" in responses[0],
            responses[0])

    def testHttpRequestWithTimeout(self):
        # And thus too http(s)get/post/... and friends.
        get_request = []
        port = PortNumberGenerator.next()

        def slowData():
            for i in xrange(5):
                yield i
                sleep(0.01)

        responses = []

        def handlerFactory(timeout):
            def gethandler(*args, **kwargs):
                try:
                    response = yield httprequest(
                        method='GET',
                        host='localhost',
                        port=port,
                        request='/path',
                        headers={
                            'Content-Type': 'text/plain',
                            'Content-Length': 0,
                            'Host': 'localhost'
                        },
                        timeout=timeout,
                    )
                    responses.append(response)
                except TimeoutException, e:
                    responses.append(e)
                finally:
                    assert responses, 'Either a timeout or response should have occurred.'
예제 #35
0
        server.listen()
        sock = socket()
        sock.connect(('localhost', self.port))
        self.reactor.step()
        sock.send("GET / HTTP/1.0\r\n\r\n")
        sock.shutdown(SHUT_RDWR)
        with stderr_replaced() as f:
            while not exceptions:
                self.reactor.step()

            self.assertTrue("Error while sending data \"%s" % yielded_data[:10] in f.getvalue())
            self.assertTrue("Traceback" in f.getvalue())
            self.assertTrue("[Errno 32] Broken pipe" in f.getvalue())

        self.assertEquals("[Errno 32] Broken pipe", str(exceptions[0]))
        server.shutdown()
        sock.close()

        self.reactor.removeTimer(token=token)

    def testHandlerExitsWithException(self):
        exceptions = []
        exc_message = "this is not an I/O exception, but an application exception"
        yielded_data = "a bit of data"
        def handler(**kwargs):
            yield yielded_data
            raise Exception(exc_message)
            yield
        server = HttpServer(self.reactor, self.port, handler, maxConnections=5)
        server.listen()
        sock = socket()
예제 #36
0
class AsyncReaderTest(WeightlessTestCase):
    def setUp(self):
        WeightlessTestCase.setUp(self)
        self.port = PortNumberGenerator.next()
        self.httpserver = HttpServer(self.reactor, self.port, self._dispatch)
        self.httpserver.listen()

    def tearDown(self):
        self.httpserver.shutdown()
        WeightlessTestCase.tearDown(self)

    def testRequestLine(self):
        self.assertEquals('GET / HTTP/1.0\r\n', _requestLine('GET', '/'))
        self.assertEquals('POST / HTTP/1.0\r\n', _requestLine('POST', '/'))

    def testEmptyRequestConvenientlyTranslatedToSlash(self):
        self.assertEquals('GET / HTTP/1.0\r\n', _requestLine('GET', ''))
        self.assertEquals('POST / HTTP/1.0\r\n', _requestLine('POST', ''))

    def testPassRequestThruToBackOfficeServer(self):
        backofficeport = PortNumberGenerator.next()
        def passthruhandler(*args, **kwargs):
            request = kwargs['RequestURI']
            response = yield httpget('localhost', backofficeport, request)
            yield response
        self.handler = passthruhandler
        expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n"
        responses = (i for i in ['hel', 'lo!'])
        backofficeserver = testserver(backofficeport, responses, expectedrequest)
        client = clientget('localhost', self.port, '/depot?arg=1&arg=2')
        self._loopReactorUntilDone()
        response = client.recv(99)
        self.assertEquals('hello!', response)

    def testPassRequestThruToBackOfficeServerWithHttpRequest(self):
        backofficeport = PortNumberGenerator.next()
        def passthruhandler(*args, **kwargs):
            request = kwargs['RequestURI']
            response = yield HttpRequest().httprequest(host='localhost', port=backofficeport, request=request)
            yield response
        self.handler = passthruhandler
        expectedrequest = "GET /depot?arg=1&arg=2 HTTP/1.0\r\n\r\n"
        responses = (i for i in ['hel', 'lo!'])
        backofficeserver = testserver(backofficeport, responses, expectedrequest)
        client = clientget('localhost', self.port, '/depot?arg=1&arg=2')
        self._loopReactorUntilDone()
        response = client.recv(99)
        self.assertEquals('hello!', response)

    @stderr_replaced
    def testConnectFails(self):
        def failingserver(*args, **kwarg):
            response = yield httpget(*target)

        self.handler = failingserver

        clientget('localhost', self.port, '/')
        target = ('localhost', 'port', '/') # non-numeric port
        self._loopReactorUntilDone()

        expectedTraceback = ignoreLineNumbers("""Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 85, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 78, in httprequest
    result = s.getResult()
  File "%(suspend.py)s", line 34, in __call__
    self._doNext(self)
  File "%(httprequest.py)s", line 35, in _do
    sok.connect((host, port))
  File "<string>", line 1, in connect
TypeError: an integer is required
       """ % fileDict)
        if PYVERSION == "2.7":
            expectedTraceback = ignoreLineNumbers("""Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 85, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 78, in httprequest
    result = s.getResult()
  File "%(suspend.py)s", line 34, in __call__
    self._doNext(self)
  File "%(httprequest.py)s", line 35, in _do
    sok.connect((host, port))
  File "/usr/lib/python2.7/socket.py", line [#], in meth
    return getattr(self._sock,name)(*args)
TypeError: an integer is required
       """ % fileDict)
        self.assertEquals(TypeError, self.error[0])
        self.assertEqualsWS(expectedTraceback, ignoreLineNumbers(''.join(format_exception(*self.error))))

        target = ('localhost', 87, '/') # invalid port
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(IOError, self.error[0])

        target = ('UEYR^$*FD(#>NDJ.khfd9.(*njnd', PortNumberGenerator.next(), '/') # invalid host
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(SocketGaiError, self.error[0])

        target = ('127.0.0.1', PortNumberGenerator.next(), '/')  # No-one listens
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()
        self.assertEquals(IOError, self.error[0])
        self.assertEquals('111', str(self.error[1]))

    @stdout_replaced
    def testTracebackPreservedAcrossSuspend(self):
        backofficeport = PortNumberGenerator.next()
        expectedrequest = ''
        testserver(backofficeport, [], expectedrequest)
        target = ('localhost', backofficeport, '/')

        exceptions = []
        def failingserver(*args, **kwarg):
            response = yield httpget(*target)
        self.handler = failingserver

        def requestLine(self, *args, **kwargs):
            raise RuntimeError("Boom!")

        try:
            originalRequestLine = httpRequestModule._requestLine
            httpRequestModule._requestLine = requestLine

            clientget('localhost', self.port, '/')
            with stderr_replaced():
                self._loopReactorUntilDone()

            expectedTraceback = ignoreLineNumbers("""Traceback (most recent call last):
  File "%(__file__)s", line 0, in handle
      yield self.handler(*args, **kwargs)
  File "%(__file__)s", line 192, in failingserver
    response = yield httpget(*target)
  File "%(httprequest.py)s", line 129, in httprequest
    result = s.getResult()
  File "%(httprequest.py)s", line 83, in _do
    yield _sendHttpHeaders(sok, method, request, headers)
  File "%(httprequest.py)s", line 121, in _sendHttpHeaders
    data = _requestLine(method, request)
  File "%(__file__)s", line 198, in requestLine
    raise RuntimeError("Boom!")
RuntimeError: Boom!""" % fileDict)
            resultingTraceback = ''.join(format_exception(*self.error))
            self.assertEqualsWS(expectedTraceback, ignoreLineNumbers(resultingTraceback))

        finally:
            httpRequestModule._requestLine = originalRequestLine

    def testHttpPost(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request)
        body = u"BÖDY" * 20000
        responses = []
        def posthandler(*args, **kwargs):
            response = yield httppost('localhost', port, '/path', body,
                    headers={'Content-Type': 'text/plain'}
            )
            yield response
            responses.append(response)
        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(['Content-Length: 100000\r\n', 'Content-Type: text/plain\r\n'], headers)
        self.assertEquals(body, post_request[0]['body'])

    def testHttpPostWithoutHeaders(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request)
        body = u"BÖDY" * 20000
        responses = []
        def posthandler(*args, **kwargs):
            response = yield httppost('localhost', port, '/path', body)
            yield response
            responses.append(response)
        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(['Content-Length: 100000\r\n'], headers)
        self.assertEquals(body, post_request[0]['body'])

    def testHttpsPost(self):
        post_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, post_request, ssl=True)
        body = u"BÖDY" * 20000
        responses = []
        def posthandler(*args, **kwargs):
            response = yield httpspost('localhost', port, '/path', body,
                    headers={'Content-Type': 'text/plain'}
            )
            yield response
            responses.append(response)
        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("POST RESPONSE" in responses[0], responses[0])
        self.assertEquals('POST', post_request[0]['command'])
        self.assertEquals('/path', post_request[0]['path'])
        headers = post_request[0]['headers'].headers
        self.assertEquals(['Content-Length: 100000\r\n', 'Content-Type: text/plain\r\n'], headers)
        self.assertEquals(body, post_request[0]['body'])

    @stderr_replaced
    def testHttpsPostOnIncorrectPort(self):
        responses = []
        def posthandler(*args, **kwargs):
            response = yield httpspost('localhost', PortNumberGenerator.next(), '/path', "body",
                    headers={'Content-Type': 'text/plain'}
            )
            yield response
            responses.append(response)
        self.handler = posthandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue(self.error[0] is IOError)
        self.assertEquals("111", str(self.error[1]))

    def testHttpGet(self):
        get_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, get_request)

        responses = []
        def gethandler(*args, **kwargs):
            response = 'no response yet'
            try:
                response = yield httpget('localhost', port, '/path',
                        headers={'Content-Type': 'text/plain', 'Content-Length': 0},
                        prio=4
                )
            finally:
                responses.append(response)
            yield 'HTTP/1.0 200 OK\r\n\r\n'
        self.handler = gethandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("GET RESPONSE" in responses[0], responses[0])
        self.assertEquals('GET', get_request[0]['command'])
        self.assertEquals('/path', get_request[0]['path'])
        headers = get_request[0]['headers'].headers
        self.assertEquals(['Content-Length: 0\r\n', 'Content-Type: text/plain\r\n'], headers)

    def testHttpRequest(self):
        get_request = []
        port = PortNumberGenerator.next()
        self.referenceHttpServer(port, get_request)

        responses = []
        def gethandler(*args, **kwargs):
            response = 'no response yet'
            try:
                response = yield httprequest(method='MYMETHOD', host='localhost', port=port, request='/path',
                    headers={'Content-Type': 'text/plain', 'Content-Length': 0},
                    prio=4
                )
            finally:
                responses.append(response)
            yield 'HTTP/1.0 200 OK\r\n\r\n'
        self.handler = gethandler
        clientget('localhost', self.port, '/')
        self._loopReactorUntilDone()

        self.assertTrue("Message: Unsupported method ('MYMETHOD')" in responses[0], responses[0])

    def testHttpRequestWithTimeout(self):
        # And thus too http(s)get/post/... and friends.
        get_request = []
        port = PortNumberGenerator.next()
        def slowData():
            for i in xrange(5):
                yield i
                sleep(0.01)

        responses = []
        def handlerFactory(timeout):
            def gethandler(*args, **kwargs):
                try:
                    response = yield httprequest(method='GET', host='localhost', port=port, request='/path',
                        headers={'Content-Type': 'text/plain', 'Content-Length': 0, 'Host': 'localhost'},
                        timeout=timeout,
                    )
                    responses.append(response)
                except TimeoutException, e:
                    responses.append(e)
                finally:
                    assert responses, 'Either a timeout or response should have occurred.'
예제 #37
0
    def testSuspendTimingProtocol(self):
        # happy path for timing out and not timing out
        def test(expectTimeout):
            count = []
            timedOut = []

            @identify
            def workInSuspendGenF():
                this = yield
                suspend = yield
                suspend._reactor.addProcess(process=this.next)
                try:
                    for i in xrange(5):
                        count.append(True)
                        yield
                    while True:
                        sleep(0.0001)
                        if not expectTimeout:
                            break
                        yield
                    suspend.resume('retval')
                except TimeoutException:
                    timedOut.append(True)
                finally:
                    suspend._reactor.removeProcess(process=this.next)
                yield  # Wait for GC

            def workInSuspend():
                g = workInSuspendGenF()

                def doNext(suspend):
                    g.send(suspend)

                def onTimeout():
                    g.throw(TimeoutException, TimeoutException(), None)

                return doNext, onTimeout

            def suspendWrap():
                doNext, onTimeout = workInSuspend()
                s = Suspend(doNext=doNext, timeout=0.01, onTimeout=onTimeout)
                yield s
                result = s.getResult()
                if expectTimeout:
                    self.fail('Should not have come here')
                raise StopIteration(result)

            try:
                result = yield suspendWrap()
                if expectTimeout:
                    self.fail()
            except TimeoutException:
                self.assertEquals(5, len(count))
                self.assertEquals(expectTimeout, bool(timedOut))

            if not expectTimeout:
                self.assertEquals('retval', result)

            testRun.append(True)

        # Simple driver - timing out
        testRun = []
        asProcess(test(expectTimeout=True))
        self.assertEquals(True, bool(testRun))

        # Simple driver - not timing out
        del testRun[:]
        asProcess(test(expectTimeout=False))
        self.assertEquals(True, bool(testRun))

        # http server - timing out
        reactor0 = self.reactor
        self.reactor = reactor1 = Reactor()
        del testRun[:]
        port = PortNumberGenerator.next()

        def reqHandler(**whatever):
            def inner():
                yield test(expectTimeout=True)
                yield 'HTTP/1.0 200 OK\r\n\r\n'

            return compose(inner())

        servert = HttpServer(reactor=self.reactor,
                             port=port,
                             generatorFactory=reqHandler,
                             bindAddress='127.42.42.42')

        servert.listen()
        with self.loopingReactor():
            sok = self.httpGet(host='127.42.42.42', port=port, path='/ignored')
            allData = ''
            try:
                while allData != 'HTTP/1.0 200 OK\r\n\r\n':
                    allData += sok.recv(4096)
            finally:
                servert.shutdown()
        self.assertEquals(True, bool(testRun))

        # http server - not timing out
        self.reactor = reactor2 = Reactor()
        del testRun[:]
        port = PortNumberGenerator.next()

        def reqHandler(**whatever):
            def inner():
                yield test(expectTimeout=False)
                yield 'HTTP/1.0 200 OK\r\n\r\n'

            return compose(inner())

        servert = HttpServer(reactor=self.reactor,
                             port=port,
                             generatorFactory=reqHandler,
                             bindAddress='127.42.42.42')

        servert.listen()
        with self.loopingReactor():
            sok = self.httpGet(host='127.42.42.42', port=port, path='/ignored')
            allData = ''
            try:
                while allData != 'HTTP/1.0 200 OK\r\n\r\n':
                    allData += sok.recv(4096)
            finally:
                servert.shutdown()
        self.assertEquals(True, bool(testRun))

        # cleanup (most) stuff
        reactor0.shutdown()
        reactor1.shutdown()
        reactor2.shutdown()