Beispiel #1
0
    def test_write_header(self, write_method):
        writer = HttpWriter(None, None, None, None)
        writer.status = 200
        writer['foo'] = 'bar'
        writer.flush()

        write_method.assert_called_with(b'HTTP/1.1 200 OK\r\nfoo: bar\r\n\r\n')
Beispiel #2
0
    def test_write_status(self, write_method):
        writer = HttpWriter(None, None, None, None)

        writer.write_status(b'200 OK')
        self.assertFalse(writer._headers_sent)
        writer.flush()
        self.assertTrue(writer._headers_sent)
        write_method.assert_called_with(b'HTTP/1.1 200 OK\r\n\r\n')
Beispiel #3
0
    def test_status_written(self):
        writer = HttpWriter(None, None, None, None)
        self.assertFalse(writer._headers_sent)

        writer._status_written = self._headers_sent = True

        writer.restore()

        self.assertFalse(writer._headers_sent)
Beispiel #4
0
    def test_write_header(self, write_method):
        writer = HttpWriter(None, None, None, None)
        writer.write_status(b'200 OK')
        writer.write_header(b'foo', b'bar')
        writer.flush()

        write_method.assert_called_with(b'HTTP/1.1 200 OK\r\nfoo: bar\r\n\r\n')
Beispiel #5
0
    def test_maybe_finalize_headers(self, write_method):
        writer = HttpWriter(None, None, None, None)
        writer._maybe_send_headers()
        write_method.assert_called_with(b'\r\n')

        writer = HttpWriter(None, None, None, None)
        writer._headers_sent = True
        writer._maybe_send_headers()
        self.assertTrue(writer._headers_sent)
Beispiel #6
0
    def connection_made(self, transport):
        self._transport = transport
        self._reader.set_transport(transport)

        self._writer = HttpWriter(transport, self,
                            self._reader,
                            self._loop)

        self._handler = self._build_handler()

        self._task = asyncio.async(self._handle_client())
        self._task.add_done_callback(self._maybe_log_exception)

        self._reset_timeout()
Beispiel #7
0
 def test_writelines(self):
     mtransport = unittest.mock.MagicMock()
     writer = HttpWriter(mtransport, None, None, None)
     writer.writelines((b'Hello',))
     self.assertTrue(writer._headers_sent)
     mtransport.writelines.assert_called_with((b'Hello',))
Beispiel #8
0
 def test_write_body(self, write_method):
     writer = HttpWriter(None, None, None, None)
     writer.write_body(b'hello')
     self.assertTrue(writer._headers_sent)
     write_method.assert_called_with(b'hello')
Beispiel #9
0
    def test_write_headers(self, write_header_method):
        writer = HttpWriter(None, None, None, None)

        writer.write_headers(((b'foo', b'bar'),))
        write_header_method.assert_called_with(b'foo', b'bar')
Beispiel #10
0
 def test_write_header_raises_when_headers_sent(self):
     writer = HttpWriter(None, None, None, None)
     writer._headers_sent = True
     self.assertRaises(AssertionError, writer.write_header, b'foo', b'bar')
Beispiel #11
0
    def test_write_headers(self, write_header_method):
        writer = HttpWriter(None, None, None, None)

        writer.add_headers(('foo', 'bar'))
        write_header_method.assert_called_with('foo', 'bar')
Beispiel #12
0
class BaseHttpProtocol(asyncio.StreamReaderProtocol):
    handler_factory = BaseHandler
    def __init__(self, *, keep_alive=None, loop=None):
        if keep_alive is None:
            keep_alive = _DEFAULT_KEEP_ALIVE
        self._reader = asyncio.StreamReader(loop=loop)
        self._keep_alive = keep_alive
        super().__init__(self._reader, None, loop)
        self.h_timeout = None

    def connection_made(self, transport):
        self._transport = transport
        self._reader.set_transport(transport)

        self._writer = HttpWriter(transport, self,
                            self._reader,
                            self._loop)

        self._handler = self._build_handler()

        self._task = asyncio.async(self._handle_client())
        self._task.add_done_callback(self._maybe_log_exception)

        self._reset_timeout()

    def connection_lost(self, exc):
        self._task.cancel()
        self._task = None
        handler = self._handler
        self._writer = None
        self._handler = None
        self._stop_timeout()
        try:
            handler.connection_lost(exc)
        finally:
            super().connection_lost(exc)

    def data_received(self, data):
        self._reset_timeout()
        super().data_received(data)

    @asyncio.coroutine
    def _handle_client(self):
        while True:
            try:
                req = yield from HttpParser.parse(self._reader)
            except BadRequestException as e:
                self._bad_request(self._writer, e)
                self._writer.close()
                break
            # connection has been closed
            if req is None:
                break

            try:
                yield from self._handler.handle_request(req)
            finally:
                if self._should_close_conn_immediately(req):
                    self._writer.close()
                else:
                    yield from req.body.read()
                    if self._writer is not None:
                        self._writer.restore()

    def _reset_timeout(self):
        self._stop_timeout()

        self.h_timeout = self._loop.call_later(
            self._keep_alive, self._handle_timeout)

    def _stop_timeout(self):
        if self.h_timeout is not None:
            self.h_timeout.cancel()
            self.h_timeout = None

    def _handle_timeout(self):
        if self._handler.on_timeout():
            self._reset_timeout()

    def _build_handler(self):
        return self.handler_factory(self._transport, self,
                            self._reader,
                            self._writer,
                            **self.get_handler_kwargs())

    def get_handler_kwargs(self):
        return {}

    def _should_close_conn_immediately(self, req):
        if self._keep_alive < 1:
            return True

        should_close = False
        if req.version.lower() == 'http/1.0':
            should_close = True
        conn_header = req['connection']
        if not conn_header:
            return should_close
        if conn_header == 'keep-alive':
            should_close = False
        elif conn_header == 'close':
            should_close = True
        return should_close

    def _maybe_log_exception(self, task):
        try:
            if not task.cancelled():
                task.result()
        except:
            logger.exception("An exception ocurred while serving request")
            if self._writer is not None:
                self._writer.close()