Ejemplo n.º 1
0
def test_responder_request(conn, send_status):
    events = conn.feed_data(FCGIBeginRequest(1, FCGI_RESPONDER, 0).encode())
    assert len(events) == 0

    content = encode_name_value_pairs([('REQUEST_METHOD', 'GET'), ('CONTENT_LENGTH', '')])
    events = conn.feed_data(FCGIParams(1, content).encode())
    assert len(events) == 0

    events = conn.feed_data(FCGIParams(1, b'').encode())
    assert isinstance(events[0], RequestBeginEvent)

    events = conn.feed_data(FCGIStdin(1, b'content').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestDataEvent)

    events = conn.feed_data(FCGIStdin(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestDataEvent)

    headers = [(b'Content-Length', b'7'), (b'Content-Type', b'text/plain')]
    conn.send_headers(1, headers, status=200 if send_status else None)
    expected_body = b'Content-Length: 7\r\nContent-Type: text/plain\r\n\r\n'
    if send_status:
        expected_body = b'Status: 200\r\n' + expected_body
    assert conn.data_to_send() == \
        FCGIStdout(1, expected_body).encode()

    conn.send_data(1, b'Cont')
    assert conn.data_to_send() == FCGIStdout(1, b'Cont').encode()

    conn.send_data(1, b'ent', end_request=True)
    assert conn.data_to_send() == FCGIStdout(1, b'ent').encode() + \
        FCGIStdout(1, b'').encode() + FCGIEndRequest(1, 0, FCGI_REQUEST_COMPLETE).encode()
Ejemplo n.º 2
0
    def end_request(self, request_id):
        """
        Mark the given request finished.

        :param int request_id: identifier of the request
        :raise fcgiproto.ProtocolError: if the protocol is violated

        """
        self._send_record(FCGIEndRequest(request_id, 0, FCGI_REQUEST_COMPLETE))
Ejemplo n.º 3
0
    def send_data(self, request_id, data, end_request=False):
        """
        Send response body data for the given request.

        This method may be called several times before :meth:`.end_request`.

        :param int request_id: identifier of the request
        :param bytes data: request body data
        :param bool end_request: ``True`` to finish the request
        :raise fcgiproto.ProtocolError: if the protocol is violated

        """
        self._send_record(FCGIStdout(request_id, data))
        if end_request:
            self._send_record(FCGIStdout(request_id, b''))
            self._send_record(FCGIEndRequest(request_id, 0, FCGI_REQUEST_COMPLETE))
Ejemplo n.º 4
0
def test_aborted_request(conn):
    events = conn.feed_data(FCGIBeginRequest(1, FCGI_RESPONDER, 0).encode())
    assert len(events) == 0

    content = encode_name_value_pairs([('REQUEST_METHOD', 'GET'), ('CONTENT_LENGTH', '')])
    events = conn.feed_data(FCGIParams(1, content).encode())
    assert len(events) == 0

    events = conn.feed_data(FCGIParams(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestBeginEvent)

    events = conn.feed_data(FCGIStdin(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestDataEvent)

    events = conn.feed_data(FCGIAbortRequest(1).encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestAbortEvent)

    conn.end_request(1)
    assert conn.data_to_send() == FCGIEndRequest(1, 0, FCGI_REQUEST_COMPLETE).encode()
Ejemplo n.º 5
0
def test_filter_request():
    conn = FastCGIConnection(roles=[FCGI_FILTER])
    events = conn.feed_data(FCGIBeginRequest(1, FCGI_FILTER, 0).encode())
    assert len(events) == 0

    content = encode_name_value_pairs([('REQUEST_METHOD', 'GET'), ('CONTENT_LENGTH', '')])
    events = conn.feed_data(FCGIParams(1, content).encode())
    assert len(events) == 0

    events = conn.feed_data(FCGIParams(1, b'').encode())
    assert isinstance(events[0], RequestBeginEvent)

    events = conn.feed_data(FCGIStdin(1, b'content').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestDataEvent)

    events = conn.feed_data(FCGIStdin(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestDataEvent)

    events = conn.feed_data(FCGIData(1, b'file data').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestSecondaryDataEvent)

    events = conn.feed_data(FCGIData(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestSecondaryDataEvent)

    headers = [(b'Content-Length', b'9'), (b'Content-Type', b'application/octet-stream')]
    conn.send_headers(1, headers, status=404)
    assert conn.data_to_send() == \
        FCGIStdout(1, b'Status: 404\r\nContent-Length: 9\r\n'
                      b'Content-Type: application/octet-stream\r\n\r\n').\
        encode()

    conn.send_data(1, b'file data', end_request=True)
    assert conn.data_to_send() == FCGIStdout(1, b'file data').encode() + \
        FCGIStdout(1, b'').encode() + FCGIEndRequest(1, 0, FCGI_REQUEST_COMPLETE).encode()
Ejemplo n.º 6
0
    def feed_data(self, data):
        """
        Feed data to the internal buffer of the connection.

        If there is enough data to generate one or more events, they will be added to the list
        returned from this call.

        Sometimes this call generates outgoing data so it is important to call
        :meth:`.data_to_send` afterwards and write those bytes to the output.

        :param bytes data: incoming data
        :raise fcgiproto.ProtocolError: if the protocol is violated
        :return: the list of generated FastCGI events
        :rtype: list

        """
        self._input_buffer.extend(data)
        events = []
        while True:
            record = decode_record(self._input_buffer)
            if record is None:
                return events

            if record.request_id:
                request_state = self._request_states[record.request_id]
                event = request_state.receive_record(record)
                if record.record_type == FCGI_BEGIN_REQUEST and record.role not in self.roles:
                    # Reject requests where the role isn't among our set of allowed roles
                    self._send_record(FCGIEndRequest(record.request_id, 0, FCGI_UNKNOWN_ROLE))
                elif event is not None:
                    events.append(event)
            else:
                if record.record_type == FCGI_GET_VALUES:
                    pairs = [(key, self.fcgi_values[key]) for key in record.keys
                             if key in self.fcgi_values]
                    self._send_record(FCGIGetValuesResult(pairs))
                else:
                    self._send_record(FCGIUnknownType(record.record_type))
Ejemplo n.º 7
0
def test_authorizer_request():
    conn = FastCGIConnection(roles=[FCGI_AUTHORIZER])
    events = conn.feed_data(FCGIBeginRequest(1, FCGI_AUTHORIZER, 0).encode())
    assert len(events) == 0

    content = encode_name_value_pairs([('REQUEST_METHOD', 'GET'), ('CONTENT_LENGTH', '')])
    events = conn.feed_data(FCGIParams(1, content).encode())
    assert len(events) == 0

    events = conn.feed_data(FCGIParams(1, b'').encode())
    assert len(events) == 1
    assert isinstance(events[0], RequestBeginEvent)

    headers = [(b'Content-Length', b'13'), (b'Content-Type', b'text/plain')]
    conn.send_headers(1, headers, status=403)
    assert conn.data_to_send() == \
        FCGIStdout(1, b'Status: 403\r\nContent-Length: 13\r\n'
                      b'Content-Type: text/plain\r\n\r\n').encode()

    conn.send_data(1, b'Access denied', end_request=True)
    assert conn.data_to_send() == \
        FCGIStdout(1, b'Access denied').encode() + FCGIStdout(1, b'').encode() + \
        FCGIEndRequest(1, 0, FCGI_REQUEST_COMPLETE).encode()
Ejemplo n.º 8
0
def test_unknown_role(conn):
    events = conn.feed_data(FCGIBeginRequest(1, FCGI_AUTHORIZER, 0).encode())
    assert len(events) == 0
    assert conn.data_to_send() == FCGIEndRequest(1, 0, FCGI_UNKNOWN_ROLE).encode()
Ejemplo n.º 9
0
    RequestDataEvent, RequestAbortEvent, RequestBeginEvent, RequestSecondaryDataEvent)
from fcgiproto.exceptions import ProtocolError
from fcgiproto.records import (
    FCGIStdin, FCGIData, FCGIAbortRequest, FCGIStdout, FCGIEndRequest, FCGIBeginRequest,
    FCGIParams, encode_name_value_pairs)
from fcgiproto.states import RequestState

begin_record = FCGIBeginRequest(1, FCGI_RESPONDER, 0)
params_record = FCGIParams(1, encode_name_value_pairs([('NAME', 'VALUE')]))
params_end_record = FCGIParams(1, b'')
stdin_record = FCGIStdin(1, b'')
data_record = FCGIData(1, b'')
abort_record = FCGIAbortRequest(1)
stdout_record = FCGIStdout(1, b'content')
stdout_end_record = FCGIStdout(1, b'')
end_record = FCGIEndRequest(1, 0, FCGI_REQUEST_COMPLETE)
end_record_reject = FCGIEndRequest(1, 0, FCGI_UNKNOWN_ROLE)


class BaseStateTests(object):
    possible_states = {RequestState.EXPECT_BEGIN_REQUEST,
                       RequestState.EXPECT_PARAMS,
                       RequestState.EXPECT_STDIN,
                       RequestState.EXPECT_DATA,
                       RequestState.EXPECT_STDOUT,
                       RequestState.EXPECT_END_REQUEST,
                       RequestState.FINISHED}
    role = None

    @pytest.mark.parametrize('allowed_states, record, expected_event_class', [
        ([RequestState.EXPECT_BEGIN_REQUEST], begin_record, type(None)),
Ejemplo n.º 10
0
def test_encode_end_request():
    record = FCGIEndRequest(5, 65537, 2)
    assert record.encode(
    ) == b'\x01\x03\x00\x05\x00\x08\x00\x00\x00\x01\x00\x01\x02\x00\x00\x00'
Ejemplo n.º 11
0
def test_parse_end_request():
    buffer = bytearray(b'\x00\x01\x00\x01\x02\x00\x00\x00')
    record = FCGIEndRequest.parse(5, buffer)
    assert record.request_id == 5
    assert record.app_status == 65537
    assert record.protocol_status == 2