1#!/usr/bin/env python3 2# Copyright (c) 2014-2019 The Bitcoin Core developers 3# Distributed under the MIT software license, see the accompanying 4# file COPYING or http://www.opensource.org/licenses/mit-license.php. 5"""Test the RPC HTTP basics.""" 6 7from test_framework.test_framework import BitcoinTestFramework 8from test_framework.util import assert_equal, str_to_b64str 9 10import http.client 11import urllib.parse 12 13class HTTPBasicsTest (BitcoinTestFramework): 14 def set_test_params(self): 15 self.num_nodes = 3 16 self.supports_cli = False 17 18 def setup_network(self): 19 self.setup_nodes() 20 21 def run_test(self): 22 23 ################################################# 24 # lowlevel check for http persistent connection # 25 ################################################# 26 url = urllib.parse.urlparse(self.nodes[0].url) 27 authpair = url.username + ':' + url.password 28 headers = {"Authorization": "Basic " + str_to_b64str(authpair)} 29 30 conn = http.client.HTTPConnection(url.hostname, url.port) 31 conn.connect() 32 conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) 33 out1 = conn.getresponse().read() 34 assert b'"error":null' in out1 35 assert conn.sock is not None #according to http/1.1 connection must still be open! 36 37 #send 2nd request without closing connection 38 conn.request('POST', '/', '{"method": "getchaintips"}', headers) 39 out1 = conn.getresponse().read() 40 assert b'"error":null' in out1 #must also response with a correct json-rpc message 41 assert conn.sock is not None #according to http/1.1 connection must still be open! 42 conn.close() 43 44 #same should be if we add keep-alive because this should be the std. behaviour 45 headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"} 46 47 conn = http.client.HTTPConnection(url.hostname, url.port) 48 conn.connect() 49 conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) 50 out1 = conn.getresponse().read() 51 assert b'"error":null' in out1 52 assert conn.sock is not None #according to http/1.1 connection must still be open! 53 54 #send 2nd request without closing connection 55 conn.request('POST', '/', '{"method": "getchaintips"}', headers) 56 out1 = conn.getresponse().read() 57 assert b'"error":null' in out1 #must also response with a correct json-rpc message 58 assert conn.sock is not None #according to http/1.1 connection must still be open! 59 conn.close() 60 61 #now do the same with "Connection: close" 62 headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"} 63 64 conn = http.client.HTTPConnection(url.hostname, url.port) 65 conn.connect() 66 conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) 67 out1 = conn.getresponse().read() 68 assert b'"error":null' in out1 69 assert conn.sock is None #now the connection must be closed after the response 70 71 #node1 (2nd node) is running with disabled keep-alive option 72 urlNode1 = urllib.parse.urlparse(self.nodes[1].url) 73 authpair = urlNode1.username + ':' + urlNode1.password 74 headers = {"Authorization": "Basic " + str_to_b64str(authpair)} 75 76 conn = http.client.HTTPConnection(urlNode1.hostname, urlNode1.port) 77 conn.connect() 78 conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) 79 out1 = conn.getresponse().read() 80 assert b'"error":null' in out1 81 82 #node2 (third node) is running with standard keep-alive parameters which means keep-alive is on 83 urlNode2 = urllib.parse.urlparse(self.nodes[2].url) 84 authpair = urlNode2.username + ':' + urlNode2.password 85 headers = {"Authorization": "Basic " + str_to_b64str(authpair)} 86 87 conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) 88 conn.connect() 89 conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) 90 out1 = conn.getresponse().read() 91 assert b'"error":null' in out1 92 assert conn.sock is not None #connection must be closed because bitcoind should use keep-alive by default 93 94 # Check excessive request size 95 conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) 96 conn.connect() 97 conn.request('GET', '/' + ('x'*1000), '', headers) 98 out1 = conn.getresponse() 99 assert_equal(out1.status, http.client.NOT_FOUND) 100 101 conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port) 102 conn.connect() 103 conn.request('GET', '/' + ('x'*10000), '', headers) 104 out1 = conn.getresponse() 105 assert_equal(out1.status, http.client.BAD_REQUEST) 106 107 108if __name__ == '__main__': 109 HTTPBasicsTest ().main () 110