Пример #1
0
    def test_read_line_to_piece(self):
        ''' Make sure _handle_data() reads pieces after lines '''
        client = http_clnt.HttpClient()
        context = http_clnt.ClientContext({}, None, None)
        stream = FakeStream(context)
        self.pieces = []  # Start over
        self.lines = []  # Start over
        context.handle_piece = self.handle_piece
        context.handle_line = self.handle_line

        bytez = six.b('').join([
            six.b('HTTP/1.1 200 Ok\r\n'),
            six.b('Content-Type: text/plain\r\n'),
            six.b('Server: Neubot/0.0.1.0\r\n'),
            six.b('\r\n'),
            six.b('A') * 64
        ])
        client._handle_data(stream, bytez)
        self.assertEqual(len(self.lines), 4)
        self.assertEqual(self.lines[0], six.b('HTTP/1.1 200 Ok\r\n'))
        self.assertEqual(self.lines[1], six.b('Content-Type: text/plain\r\n'))
        self.assertEqual(self.lines[2], six.b('Server: Neubot/0.0.1.0\r\n'))
        self.assertEqual(self.lines[3], six.b('\r\n'))

        context.left = 64
        client._handle_data(stream, bytez)
        self.assertEqual(context.left, 0)
        self.assertEqual(len(self.pieces), 1)
        self.assertEqual(self.pieces[0], six.b('A') * 64)
Пример #2
0
 def test_append_file(self):
     ''' Make sure append_file() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_file(stream, '1234')  # Whathever works
     self.assertEqual(context.outfp, '1234')
Пример #3
0
 def test_protocol_version(self):
     ''' Make sure _handle_firstline() requires HTTP/1.{0,1} protocol '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.assertRaises(RuntimeError, client._handle_firstline, stream,
                       six.b('HTTP/1.2 200 Ok\r\n'))
Пример #4
0
 def test_append_end_of_headers(self):
     ''' Make sure append_end_of_headers() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_end_of_headers(stream)
     self.assertEqual(context.outq[0], http_clnt.CRLF)
     self.assertEqual(len(context.outq), 1)
Пример #5
0
 def test_eoh_empty(self):
     ''' Make sure _handle_header_ex() recognizes EOH w/ empty string '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream, six.b(''), self.handle_done)
     self.assertEqual(self.handle_done_cnt, 1)
Пример #6
0
 def test_readline_too_long(self):
     ''' Make sure _handle_data() fails when reading too-long lines '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     bytez = six.b('A') * http_clnt.MAXLINE
     # Note: failure because no LF at line[MAXLINE -1]
     self.assertRaises(RuntimeError, client._handle_data, stream, bytez)
Пример #7
0
 def test_header_badfmt(self):
     ''' Make sure _handle_header_ex() errs out on bad header format '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.assertRaises(RuntimeError, client._handle_header_ex, stream,
                       six.b('Content-Type text/plain\r\n'),
                       self.handle_done)
Пример #8
0
 def test_append_bytes(self):
     ''' Make sure append_bytes() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_bytes(stream, six.b('A') * 512)
     self.assertEqual(context.outq[0], six.b('A') * 512)
     self.assertEqual(len(context.outq), 1)
Пример #9
0
 def test_no_data_open(self):
     ''' Make sure _handle_data() works for no data and open stream '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client._handle_data(stream, six.b(''))
     # Make sure the code schedules the next recv
     self.assertEqual(stream.count, http_clnt.MAXRECEIVE)
     self.assertEqual(stream.func, client._handle_data)
Пример #10
0
    def test_fp_body(self):
        ''' Make sure send_message() works with filep body '''

        client = http_clnt.HttpClient()
        context = http_clnt.ClientContext({}, None, None)
        stream = FakeStream(context)
        client.append_request(stream, 'GET', '/', 'HTTP/1.0')
        client.append_header(stream, 'Accept', 'text/plain')
        client.append_header(stream, 'User-Agent', 'Neubot/0.0.1.0')
        client.append_header(stream, 'Content-Length',
                             str(3 * http_clnt.MAXREAD - 4))
        client.append_header(stream, 'Content-Type', 'text/plain')
        client.append_end_of_headers(stream)
        stringio = six.BytesIO(six.b('A') * (3 * http_clnt.MAXREAD - 4))
        client.append_file(stream, stringio)

        # Make sure send_complete is called just once and at the end
        self.send_complete_cnt = 0
        client.handle_send_complete = self.handle_send_complete

        # First send() sends just the request headers and should not
        # invoke the send_complete() hook
        client.send_message(stream)
        self.assertEqual(
            stream.outs,
            six.b(''.join([
                'GET / HTTP/1.0\r\n', 'Accept: text/plain\r\n',
                'User-Agent: Neubot/0.0.1.0\r\n',
                'Content-Length: %d\r\n' % (3 * http_clnt.MAXREAD - 4),
                'Content-Type: text/plain\r\n', '\r\n'
            ])))
        self.assertEqual(self.send_complete_cnt, 0)

        # Second send() sends the first MAXREAD bytes and should not
        # invoke the send_complete() hook
        client._handle_send_complete(stream)
        self.assertEqual(stream.outs, six.b('A') * http_clnt.MAXREAD)
        self.assertEqual(self.send_complete_cnt, 0)

        # Third send() sends the second MAXREAD bytes and should not
        # invoke the send_complete() hook
        client._handle_send_complete(stream)
        self.assertEqual(stream.outs, six.b('A') * http_clnt.MAXREAD)
        self.assertEqual(self.send_complete_cnt, 0)

        # Fourth send() sends the third MAXREAD bytes and should not
        # invoke the send_complete() hook
        client._handle_send_complete(stream)
        self.assertEqual(stream.outs, six.b('A') * (http_clnt.MAXREAD - 4))
        self.assertEqual(self.send_complete_cnt, 0)

        # Fifth send() should cleanup things, should invoke the
        # send_complete() hook, and clear the output file
        client._handle_send_complete(stream)
        self.assertEqual(context.outfp, None)
        self.assertEqual(self.send_complete_cnt, 1)
Пример #11
0
 def test_append_chunk(self):
     ''' Make sure append_chunk() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_chunk(stream, six.b('A') * 513)
     self.assertEqual(context.outq[0], six.b('201\r\n'))
     self.assertEqual(context.outq[1], six.b('A') * 513)
     self.assertEqual(context.outq[2], http_clnt.CRLF)
     self.assertEqual(len(context.outq), 3)
Пример #12
0
 def test_no_data_closed(self):
     ''' Make sure _handle_data() works for no data and closed stream '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     stream.isclosed = 1  # Pretend the stream is closed
     client._handle_data(stream, six.b(''))
     # Make sure we don't schedule the next recv
     self.assertEqual(stream.count, 0)
     self.assertEqual(stream.func, None)
Пример #13
0
 def test_append_header(self):
     ''' Make sure append_header() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_header(stream, 'Content-Type', 'text/plain')
     self.assertEqual(context.outq[0], six.b('Content-Type'))
     self.assertEqual(context.outq[1], http_clnt.COLON)
     self.assertEqual(context.outq[2], http_clnt.SPACE)
     self.assertEqual(context.outq[3], six.b('text/plain'))
     self.assertEqual(context.outq[4], http_clnt.CRLF)
     self.assertEqual(len(context.outq), 5)
Пример #14
0
 def test_numtokens(self):
     ''' Make sure _handle_firstline() requires 3+ tokens '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.assertRaises(RuntimeError, client._handle_firstline, stream,
                       six.b(''))
     self.assertRaises(RuntimeError, client._handle_firstline, stream,
                       six.b('\r\n'))
     self.assertRaises(RuntimeError, client._handle_firstline, stream,
                       six.b('HTTP/1.0\r\n'))
     self.assertRaises(RuntimeError, client._handle_firstline, stream,
                       six.b('HTTP/1.0 200\r\n'))
Пример #15
0
 def test_success(self):
     ''' Make sure _handle_firstline() works as expected '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client._handle_firstline(stream, six.b('HTTP/1.1 404 Not Found\r\n'))
     self.assertEqual(context.protocol, six.b('HTTP/1.1'))
     self.assertEqual(context.code, six.b('404'))
     self.assertEqual(context.reason, six.b('Not Found'))
     # Make sure state is OK
     self.assertEqual(context.last_hdr, six.b(''))
     self.assertEqual(context.headers, {})
     self.assertEqual(context.handle_line, client._handle_header)
Пример #16
0
 def test_readpiece_small(self):
     ''' Make sure _handle_data() works for reading small pieces '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     bytez = six.b('A') * 7
     context.left = 7
     self.pieces = []  # Start over
     context.handle_piece = self.handle_piece
     client._handle_data(stream, bytez)
     self.assertEqual(context.left, 0)
     self.assertEqual(len(self.pieces), 1)
     self.assertEqual(self.pieces[0], six.b('A') * 7)
Пример #17
0
 def test_header_smpl(self):
     ''' Make sure _handle_header_ex() correctly parses simple headers '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream, six.b('Content-Type: text/plain\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('content-type') in context.headers)
     self.assertFalse(six.b('Content-Type') in context.headers)
     self.assertEqual(context.headers[six.b('content-type')],
                      six.b('text/plain'))
Пример #18
0
 def test_append_request(self):
     ''' Make sure append_request() works '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_request(stream, 'GET', '/', 'HTTP/1.0')
     self.assertEqual(context.method, six.b('GET'))
     self.assertEqual(context.outq[0], six.b('GET'))
     self.assertEqual(context.outq[1], http_clnt.SPACE)
     self.assertEqual(context.outq[2], six.b('/'))
     self.assertEqual(context.outq[3], http_clnt.SPACE)
     self.assertEqual(context.outq[4], six.b('HTTP/1.0'))
     self.assertEqual(context.outq[5], http_clnt.CRLF)
     self.assertEqual(len(context.outq), 6)
Пример #19
0
 def test_readline_smpl(self):
     ''' Make sure _handle_data() works for reading simple lines '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     bytez = six.b('GET / HTTP/1.0\r\nAccept: */*\r\n\r\n')
     self.lines = []  # Start over
     context.handle_line = self.handle_line
     client._handle_data(stream, bytez)
     # Make sure we have read the three lines
     self.assertEqual(len(self.lines), 3)
     self.assertEqual(self.lines[0], six.b('GET / HTTP/1.0\r\n'))
     self.assertEqual(self.lines[1], six.b('Accept: */*\r\n'))
     self.assertEqual(self.lines[2], six.b('\r\n'))
Пример #20
0
 def test_folding_tab(self):
     ''' Make sure _handle_header_ex() folds line starting with tab '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream, six.b('Content-Type: \r\n'),
                              self.handle_done)
     client._handle_header_ex(stream, six.b('\ttext/plain\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('content-type') in context.headers)
     self.assertFalse(six.b('Content-Type') in context.headers)
     self.assertEqual(context.headers[six.b('content-type')],
                      six.b('text/plain'))
Пример #21
0
 def test_no_body(self):
     ''' Make sure send_message() works without body '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     client.append_request(stream, 'GET', '/', 'HTTP/1.0')
     client.append_header(stream, 'Accept', 'text/plain')
     client.append_header(stream, 'User-Agent', 'Neubot/0.0.1.0')
     client.append_end_of_headers(stream)
     client.send_message(stream)
     self.assertEqual(
         stream.outs,
         six.b(''.join([
             'GET / HTTP/1.0\r\n', 'Accept: text/plain\r\n',
             'User-Agent: Neubot/0.0.1.0\r\n', '\r\n'
         ])))
Пример #22
0
 def test_nofolding_first_hdr(self):
     ''' Make sure _handle_header_ex() allows first header to start
         with a space or tab '''
     # This is a "feature" of Neubot's HTTP
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream,
                              six.b(' Content-Type: text/plain\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('content-type') in context.headers)
     self.assertFalse(six.b('Content-Type') in context.headers)
     self.assertEqual(context.headers[six.b('content-type')],
                      six.b('text/plain'))
Пример #23
0
    def test_blanks(self):
        ''' Make sure _handle_firstline() works as expected w/ extra blanks '''
        client = http_clnt.HttpClient()
        context = http_clnt.ClientContext({}, None, None)
        stream = FakeStream(context)

        client._handle_firstline(stream,
                                 six.b(' HTTP/1.1   404   Not Found  \r\n'))
        self.assertEqual(context.protocol, six.b('HTTP/1.1'))
        self.assertEqual(context.code, six.b('404'))
        self.assertEqual(context.reason, six.b('Not Found'))

        client._handle_firstline(stream,
                                 six.b('\tHTTP/1.1\t404\tNot Found\t\r\n'))
        self.assertEqual(context.protocol, six.b('HTTP/1.1'))
        self.assertEqual(context.code, six.b('404'))
        self.assertEqual(context.reason, six.b('Not Found'))
Пример #24
0
 def test_folding_multi(self):
     ''' Make sure _handle_header_ex() folds multiple lines '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream, six.b('Accept: \r\n'),
                              self.handle_done)
     client._handle_header_ex(stream, six.b(' application/json,\r\n'),
                              self.handle_done)
     client._handle_header_ex(stream, six.b(' text/plain\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('accept') in context.headers)
     self.assertFalse(six.b('Accept') in context.headers)
     self.assertEqual(context.headers[six.b('accept')],
                      six.b('application/json, text/plain'))
Пример #25
0
 def test_colon_in_folded_line(self):
     ''' Make sure _handle_header_ex() correctly handles colon
         in folded line '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(stream, six.b('Accept: \r\n'),
                              self.handle_done)
     client._handle_header_ex(stream, six.b(' application:json,\r\n'),
                              self.handle_done)
     client._handle_header_ex(stream, six.b(' text:plain\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('accept') in context.headers)
     self.assertFalse(six.b('Accept') in context.headers)
     self.assertEqual(context.headers[six.b('accept')],
                      six.b('application:json, text:plain'))
Пример #26
0
 def test_header_multiple_spaces(self):
     ''' Make sure _handle_header_ex() correctly parses multiple headers
         with headrs with equal name and spaces '''
     client = http_clnt.HttpClient()
     context = http_clnt.ClientContext({}, None, None)
     stream = FakeStream(context)
     self.handle_done_cnt = 0  # Start over
     client._handle_header_ex(
         stream, six.b('Content-Type :     text/plain    \r\n'),
         self.handle_done)
     client._handle_header_ex(stream,
                              six.b('Content-Type\t\t: \ttext/plain\t\r\n'),
                              self.handle_done)
     self.assertEqual(self.handle_done_cnt, 0)
     self.assertTrue(six.b('content-type') in context.headers)
     self.assertFalse(six.b('Content-Type') in context.headers)
     self.assertEqual(context.headers[six.b('content-type')],
                      six.b('text/plain, text/plain'))
Пример #27
0
    def test_readline_partial(self):
        ''' Make sure _handle_data() works for reading partial lines '''
        client = http_clnt.HttpClient()
        context = http_clnt.ClientContext({}, None, None)
        stream = FakeStream(context)
        self.lines = []  # Start over
        context.handle_line = self.handle_line

        # Here we have a partial line so nothing will happen
        bytez = six.b('GET / HTTP/1')
        client._handle_data(stream, bytez)
        self.assertEqual(len(self.lines), 0)

        # Here we resume and split the three input lines
        bytez = six.b('.0\r\nAccept: */*\r\n\r\n')
        client._handle_data(stream, bytez)
        self.assertEqual(len(self.lines), 3)
        self.assertEqual(self.lines[0], six.b('GET / HTTP/1.0\r\n'))
        self.assertEqual(self.lines[1], six.b('Accept: */*\r\n'))
        self.assertEqual(self.lines[2], six.b('\r\n'))
Пример #28
0
    def test_readpiece_large(self):
        ''' Make sure _handle_data() works for reading large pieces '''
        client = http_clnt.HttpClient()
        context = http_clnt.ClientContext({}, None, None)
        stream = FakeStream(context)
        self.pieces = []  # Start over
        context.left = http_clnt.MAXRECEIVE + 8
        context.handle_piece = self.handle_piece

        bytez = six.b('A') * (http_clnt.MAXRECEIVE + 4)
        client._handle_data(stream, bytez)
        self.assertEqual(context.left, 8)
        self.assertEqual(len(self.pieces), 1)
        self.assertEqual(self.pieces[0], six.b('A') * http_clnt.MAXRECEIVE)

        bytez = six.b('A') * 4
        client._handle_data(stream, bytez)
        self.assertEqual(context.left, 0)
        self.assertEqual(len(self.pieces), 2)
        self.assertEqual(self.pieces[0], six.b('A') * http_clnt.MAXRECEIVE)
        self.assertEqual(self.pieces[1], six.b('A') * 8)