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)
def __subcommand_daemonize(user, args): ''' `daemonize` subcommand ''' if len(args) != 0: sys.exit(USAGE) sys.stderr.write('Note: logging messages via syslog\n') logging.info('old pid: %d\n', os.getpid()) logging.info('*** now going in the background ***') daemonize(pidfile='/var/run/neubot-utils-posix.pid', sighandler=__my_handler) logging.info('*** process information after becoming a daemon ***') logging.info('new pid: %d\n', os.getpid()) logging.info('ppid: %d\n', os.getppid()) logging.info('sid: %d\n', os.getsid(0)) os.kill(os.getpid(), signal.SIGINT) logging.info('SIGINT was correctly ignored') statbuf = os.stat('/dev/null') logging.info('/dev/null: %d/%d\n', statbuf.st_dev, statbuf.st_ino) statbuf = os.fstat(0) logging.info('stdin: %d/%d\n', statbuf.st_dev, statbuf.st_ino) statbuf = os.fstat(1) logging.info('stdout: %d/%d\n', statbuf.st_dev, statbuf.st_ino) statbuf = os.fstat(2) logging.info('stderr: %d/%d\n', statbuf.st_dev, statbuf.st_ino) logging.info('read stdin: %s\n', os.read(0, 1024)) logging.info('read stdout: %s\n', os.read(1, 1024)) logging.info('read stderr: %s\n', os.read(2, 1024)) try: os.write(0, six.b('a')) except OSError: logging.info('write stdin: %s\n', sys.exc_info()[1]) logging.info('write stdout: %d\n', os.write(1, six.b('a'))) logging.info('write stderr: %d\n', os.write(2, six.b('a'))) logging.info('cwd: %s\n', os.getcwd()) os.kill(os.getpid(), signal.SIGPIPE) logging.info('SIGPIPE was correctly ignored') filep = open('/tmp/neubot-utils-posix.pid', 'r') pid = int(filep.read().strip()) filep.close() logging.info('pid from pidfile: %d', pid) logging.info('sending SIGTERM to myself') os.kill(os.getpid(), signal.SIGTERM) logging.info('sent SIGTERM to myself') logging.info('sending SIGHUP to myself') os.kill(os.getpid(), signal.SIGHUP) logging.info('sent SIGHUP to myself')
def append_header(stream, name, value): ''' Append header to output buffer ''' context = stream.opaque logging.debug('> %s: %s', name, value) context.outq.append(six.b(name)) context.outq.append(COLON) context.outq.append(SPACE) context.outq.append(six.b(value)) context.outq.append(CRLF)
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)
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)
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)
def append_request(stream, method, uri, protocol): ''' Append request to output buffer ''' context = stream.opaque logging.debug('> %s %s %s', method, uri, protocol) context.method = six.b(method) context.outq.append(six.b(method)) context.outq.append(SPACE) context.outq.append(six.b(uri)) context.outq.append(SPACE) context.outq.append(six.b(protocol)) context.outq.append(CRLF)
def __init__(self): Brigade.__init__(self) self.ticks = 0.0 self.count = 0 self.message = six.b('') self.auth = six.b('') self.state = {} self.snap_ticks = 0.0 self.snap_count = 0 self.snap_utime = 0.0 self.snap_stime = 0.0 self.web100_dirname = six.u('')
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)
def test__1(self): ''' Make sure that append() fails when it can't decode the prefix or the path ''' # Note: '/cio\xc3a8' is wrong on purpose here self.assertEqual( utils_path.append(six.b('/cio\xc3a8'), '/foobar', False), None ) self.assertEqual( utils_path.append('/foobar', six.b('/cio\xc3\xa8'), False), None )
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'))
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)
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'))
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)
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)
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'))
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'))
def handle_connection_made(self, stream): ''' Invoked when the connection is established ''' # Note: this function MUST be callable multiple times logging.debug('skype_negotiate: negotiation in progress...') context = stream.opaque extra = context.extra # TODO(claudiu) Choose a random configuration from: # voice-upstream, voice-downstream, voice-bidirectional. # Thie assumes that neubot only runs on desktop clients, so # there is no need to do a bandwidth check in order to select # which test should be performed. request = {} # No options for now request['type'] = 'voice' request['direction'] = 'upstream' request['src-port'] = 5060 body = six.b(json.dumps(request)) host_header = utils_net.format_epnt((extra['address'], extra['port'])) self.append_request(stream, 'GET', '/negotiate/skype', 'HTTP/1.1') self.append_header(stream, 'Host', host_header) self.append_header(stream, 'User-Agent', utils_version.HTTP_HEADER) self.append_header(stream, 'Content-Type', 'application/json') self.append_header(stream, 'Content-Length', str(len(body))) self.append_header(stream, 'Cache-Control', 'no-cache') self.append_header(stream, 'Pragma', 'no-cache') if extra['authorization']: self.append_header(stream, 'Authorization', extra['authorization']) self.append_end_of_headers(stream) self.append_bytes(stream, body) http_utils.prettyprint_json(request, '>') self.send_message(stream) extra['requests'] += 1
def append_chunk(stream, bytez): ''' Append chunk to output buffer ''' context = stream.opaque logging.debug('> {chunk len=%d}', len(bytez)) context.outq.append(six.b('%x\r\n' % len(bytez))) context.outq.append(bytez) context.outq.append(CRLF)
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'))
def _start_collect(self, stream, result): ''' Start the COLLECT phase ''' STATE.update('collect') logging.debug('raw_negotiate: collect in progress...') context = stream.opaque extra = context.extra extra['local_result'] = result body = six.b(json.dumps(result)) host_header = utils_net.format_epnt((extra['address'], extra['port'])) self.append_request(stream, 'POST', '/collect/raw', 'HTTP/1.1') self.append_header(stream, 'Host', host_header) self.append_header(stream, 'User-Agent', utils_version.HTTP_HEADER) self.append_header(stream, 'Content-Type', 'application/json') self.append_header(stream, 'Content-Length', str(len(body))) self.append_header(stream, 'Cache-Control', 'no-cache') self.append_header(stream, 'Pragma', 'no-cache') self.append_header(stream, 'Connection', 'close') if extra['authorization']: self.append_header(stream, 'Authorization', extra['authorization']) self.append_end_of_headers(stream) self.append_bytes(stream, body) http_utils.prettyprint_json(result, '>') self.send_message(stream) context.body = six.StringIO() # Want to save body extra['requests'] += 1
def test_decode_failure(self): ''' Make sure that possibly_decode() does not decode an invalid UTF-8 string ''' self.assertEqual( utils_path.possibly_decode(six.b("\xc2b7"), 'utf-8'), None )
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)
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)
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)
def test__3(self): ''' Verify that append() does not allow to go above the rootdir ''' self.assertEqual( utils_path.append('/foobar', '../etc/passwd', False), None ) self.assertEqual( utils_path.append('/foobar', six.b('\x2e\x2e\x2fetc\x2fpasswd'), False), None ) self.assertEqual( utils_path.append('/foobar', six.b('..%2fetc%2fpasswd'), True), None )
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)
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)
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'))
def test_bytes_body(self): ''' Make sure send_message() works with bytes-only 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', '16') client.append_header(stream, 'Content-Type', 'text/plain') client.append_end_of_headers(stream) client.append_bytes(stream, six.b('A') * 16) 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: 16\r\n', 'Content-Type: text/plain\r\n', '\r\n', 'A' * 16 ])))
def test_bytes_body(self): ''' Make sure send_message() works with bytes-only 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', '16') client.append_header(stream, 'Content-Type', 'text/plain') client.append_end_of_headers(stream) client.append_bytes(stream, six.b('A') * 16) 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: 16\r\n', 'Content-Type: text/plain\r\n', '\r\n', 'A' * 16])))
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)
def test__2(self): ''' Make sure that depth_visit() accepts a non-ascii prefix ''' visit = { "count": 0, "expect_path": [ six.b("/foo\xc3\xa8").decode("utf-8") + "/bar", six.b("/foo\xc3\xa8").decode("utf-8") + "/bar" + "/baz", ], "expect_leaf": [ False, True ], } def on_visit_called(path, leaf): ''' Just an helper function ''' self.assertEqual(path, visit["expect_path"][visit["count"]]) self.assertEqual(leaf, visit["expect_leaf"][visit["count"]]) visit["count"] += 1 utils_path.depth_visit(six.b('/foo\xc3\xa8'), ['bar', 'baz'], on_visit_called)
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'))
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'))
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'))
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'))
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'))
def getvalue(self): ''' Return bufferized data ''' data = six.b('').join(self.queue) del self.queue[:] return data