##// END OF EJS Templates
windows: make sure we fully read and cleanly close the connection...
marmoute -
r48382:6bceecb2 default
parent child Browse files
Show More
@@ -1,124 +1,131 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 """This does HTTP GET requests given a host:port and path and returns
3 """This does HTTP GET requests given a host:port and path and returns
4 a subset of the headers plus the body of the result."""
4 a subset of the headers plus the body of the result."""
5
5
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 import argparse
8 import argparse
9 import json
9 import json
10 import os
10 import os
11 import sys
11 import sys
12
12
13 from mercurial import (
13 from mercurial import (
14 pycompat,
14 pycompat,
15 util,
15 util,
16 )
16 )
17
17
18 httplib = util.httplib
18 httplib = util.httplib
19
19
20 try:
20 try:
21 import msvcrt
21 import msvcrt
22
22
23 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
23 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
24 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
24 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
25 except ImportError:
25 except ImportError:
26 pass
26 pass
27
27
28 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
28 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
29
29
30 parser = argparse.ArgumentParser()
30 parser = argparse.ArgumentParser()
31 parser.add_argument('--twice', action='store_true')
31 parser.add_argument('--twice', action='store_true')
32 parser.add_argument('--headeronly', action='store_true')
32 parser.add_argument('--headeronly', action='store_true')
33 parser.add_argument('--json', action='store_true')
33 parser.add_argument('--json', action='store_true')
34 parser.add_argument('--hgproto')
34 parser.add_argument('--hgproto')
35 parser.add_argument(
35 parser.add_argument(
36 '--requestheader',
36 '--requestheader',
37 nargs='*',
37 nargs='*',
38 default=[],
38 default=[],
39 help='Send an additional HTTP request header. Argument '
39 help='Send an additional HTTP request header. Argument '
40 'value is <header>=<value>',
40 'value is <header>=<value>',
41 )
41 )
42 parser.add_argument('--bodyfile', help='Write HTTP response body to a file')
42 parser.add_argument('--bodyfile', help='Write HTTP response body to a file')
43 parser.add_argument('host')
43 parser.add_argument('host')
44 parser.add_argument('path')
44 parser.add_argument('path')
45 parser.add_argument('show', nargs='*')
45 parser.add_argument('show', nargs='*')
46
46
47 args = parser.parse_args()
47 args = parser.parse_args()
48
48
49 twice = args.twice
49 twice = args.twice
50 headeronly = args.headeronly
50 headeronly = args.headeronly
51 formatjson = args.json
51 formatjson = args.json
52 hgproto = args.hgproto
52 hgproto = args.hgproto
53 requestheaders = args.requestheader
53 requestheaders = args.requestheader
54
54
55 tag = None
55 tag = None
56
56
57
57
58 def request(host, path, show):
58 def request(host, path, show):
59 assert not path.startswith('/'), path
59 assert not path.startswith('/'), path
60 global tag
60 global tag
61 headers = {}
61 headers = {}
62 if tag:
62 if tag:
63 headers['If-None-Match'] = tag
63 headers['If-None-Match'] = tag
64 if hgproto:
64 if hgproto:
65 headers['X-HgProto-1'] = hgproto
65 headers['X-HgProto-1'] = hgproto
66
66
67 for header in requestheaders:
67 for header in requestheaders:
68 key, value = header.split('=', 1)
68 key, value = header.split('=', 1)
69 headers[key] = value
69 headers[key] = value
70
70
71 conn = httplib.HTTPConnection(host)
71 conn = httplib.HTTPConnection(host)
72 conn.request("GET", '/' + path, None, headers)
72 conn.request("GET", '/' + path, None, headers)
73 response = conn.getresponse()
73 response = conn.getresponse()
74 stdout.write(
74 stdout.write(
75 b'%d %s\n' % (response.status, response.reason.encode('ascii'))
75 b'%d %s\n' % (response.status, response.reason.encode('ascii'))
76 )
76 )
77 if show[:1] == ['-']:
77 if show[:1] == ['-']:
78 show = sorted(
78 show = sorted(
79 h for h, v in response.getheaders() if h.lower() not in show
79 h for h, v in response.getheaders() if h.lower() not in show
80 )
80 )
81 for h in [h.lower() for h in show]:
81 for h in [h.lower() for h in show]:
82 if response.getheader(h, None) is not None:
82 if response.getheader(h, None) is not None:
83 stdout.write(
83 stdout.write(
84 b"%s: %s\n"
84 b"%s: %s\n"
85 % (h.encode('ascii'), response.getheader(h).encode('ascii'))
85 % (h.encode('ascii'), response.getheader(h).encode('ascii'))
86 )
86 )
87 if not headeronly:
87 if headeronly:
88 # still read the body to prevent windows to be unhappy about that
89 # (this might some flakyness in test-hgweb-filelog.t on Windows)
90 data = response.read()
91 else:
88 stdout.write(b'\n')
92 stdout.write(b'\n')
89 data = response.read()
93 data = response.read()
90
94
91 if args.bodyfile:
95 if args.bodyfile:
92 bodyfh = open(args.bodyfile, 'wb')
96 bodyfh = open(args.bodyfile, 'wb')
93 else:
97 else:
94 bodyfh = stdout
98 bodyfh = stdout
95
99
96 # Pretty print JSON. This also has the beneficial side-effect
100 # Pretty print JSON. This also has the beneficial side-effect
97 # of verifying emitted JSON is well-formed.
101 # of verifying emitted JSON is well-formed.
98 if formatjson:
102 if formatjson:
99 # json.dumps() will print trailing newlines. Eliminate them
103 # json.dumps() will print trailing newlines. Eliminate them
100 # to make tests easier to write.
104 # to make tests easier to write.
101 data = pycompat.json_loads(data)
105 data = pycompat.json_loads(data)
102 lines = json.dumps(data, sort_keys=True, indent=2).splitlines()
106 lines = json.dumps(data, sort_keys=True, indent=2).splitlines()
103 for line in lines:
107 for line in lines:
104 bodyfh.write(pycompat.sysbytes(line.rstrip()))
108 bodyfh.write(pycompat.sysbytes(line.rstrip()))
105 bodyfh.write(b'\n')
109 bodyfh.write(b'\n')
106 else:
110 else:
107 bodyfh.write(data)
111 bodyfh.write(data)
108
112
109 if args.bodyfile:
113 if args.bodyfile:
110 bodyfh.close()
114 bodyfh.close()
111
115
112 if twice and response.getheader('ETag', None):
116 if twice and response.getheader('ETag', None):
113 tag = response.getheader('ETag')
117 tag = response.getheader('ETag')
114
118
119 # further try to please the windows-flakyness deity
120 conn.close()
121
115 return response.status
122 return response.status
116
123
117
124
118 status = request(args.host, args.path, args.show)
125 status = request(args.host, args.path, args.show)
119 if twice:
126 if twice:
120 status = request(args.host, args.path, args.show)
127 status = request(args.host, args.path, args.show)
121
128
122 if 200 <= status <= 305:
129 if 200 <= status <= 305:
123 sys.exit(0)
130 sys.exit(0)
124 sys.exit(1)
131 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now