##// END OF EJS Templates
py3: don’t subscript socket.error...
Manuel Jacob -
r50169:b5fe10b3 stable
parent child Browse files
Show More
@@ -1,122 +1,131 b''
1 1 #require serve
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg ci -Ama -d '1123456789 0'
7 7 adding a
8 8 $ hg serve --config server.uncompressed=True -p $HGPORT -d --pid-file=hg.pid
9 9 $ cat hg.pid >> $DAEMON_PIDS
10 10 $ cd ..
11 11 $ tinyproxy.py $HGPORT1 localhost 2>proxy.log >/dev/null </dev/null &
12 12 $ while [ ! -f proxy.pid ]; do sleep 0; done
13 13 $ cat proxy.pid >> $DAEMON_PIDS
14 14
15 15 url for proxy, stream
16 16
17 17 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone --stream http://localhost:$HGPORT/ b
18 18 streaming all changes
19 19 6 files to transfer, 412 bytes of data (reporevlogstore !)
20 20 4 files to transfer, 330 bytes of data (reposimplestore !)
21 21 transferred * bytes in * seconds (*/sec) (glob)
22 22 updating to branch default
23 23 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 24 $ cd b
25 25 $ hg verify
26 26 checking changesets
27 27 checking manifests
28 28 crosschecking files in changesets and manifests
29 29 checking files
30 30 checked 1 changesets with 1 changes to 1 files
31 31 $ cd ..
32 32
33 33 url for proxy, pull
34 34
35 35 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT/ b-pull
36 36 requesting all changes
37 37 adding changesets
38 38 adding manifests
39 39 adding file changes
40 40 added 1 changesets with 1 changes to 1 files
41 41 new changesets 83180e7845de
42 42 updating to branch default
43 43 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 $ cd b-pull
45 45 $ hg verify
46 46 checking changesets
47 47 checking manifests
48 48 crosschecking files in changesets and manifests
49 49 checking files
50 50 checked 1 changesets with 1 changes to 1 files
51 51 $ cd ..
52 52
53 53 host:port for proxy
54 54
55 55 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ c
56 56 requesting all changes
57 57 adding changesets
58 58 adding manifests
59 59 adding file changes
60 60 added 1 changesets with 1 changes to 1 files
61 61 new changesets 83180e7845de
62 62 updating to branch default
63 63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 64
65 65 proxy url with user name and password
66 66
67 67 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ d
68 68 requesting all changes
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 1 changesets with 1 changes to 1 files
73 73 new changesets 83180e7845de
74 74 updating to branch default
75 75 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 76
77 77 url with user name and password
78 78
79 79 $ http_proxy=http://user:passwd@localhost:$HGPORT1 hg clone --config http_proxy.always=True http://user:passwd@localhost:$HGPORT/ e
80 80 requesting all changes
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 1 changesets with 1 changes to 1 files
85 85 new changesets 83180e7845de
86 86 updating to branch default
87 87 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 88
89 89 bad host:port for proxy ("Protocol not supported" can happen on
90 90 misconfigured hosts)
91 91
92 92 $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f
93 93 abort: error: (Connection refused|Protocol not supported|.* actively refused it|\$EADDRNOTAVAIL\$|No route to host) (re)
94 94 [100]
95 95
96 96 do not use the proxy if it is in the no list
97 97
98 98 $ http_proxy=localhost:$HGPORT1 hg clone --config http_proxy.no=localhost http://localhost:$HGPORT/ g
99 99 requesting all changes
100 100 adding changesets
101 101 adding manifests
102 102 adding file changes
103 103 added 1 changesets with 1 changes to 1 files
104 104 new changesets 83180e7845de
105 105 updating to branch default
106 106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107
108 proxy can't connect to server
109
110 $ http_proxy=http://localhost:$HGPORT1/ hg --config http_proxy.always=True clone http://localhost:$HGPORT2/ h
111 abort: HTTP Error 404: Connection refused
112 [100]
113
107 114 $ cat proxy.log
108 115 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
109 116 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
110 117 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&stream=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
111 118 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
112 119 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
113 120 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
114 121 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
115 122 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
116 123 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
117 124 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
118 125 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
119 126 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
120 127 * - - [*] "GET http://localhost:$HGPORT/?cmd=capabilities HTTP/1.1" - - (glob)
121 128 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=batch HTTP/1.1" - - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
122 129 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT/?cmd=getbundle HTTP/1.1" - - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=83180e7845de420a1bb46896fd5fe05294f8d629&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
130 * - - [*] code 404, message Connection refused (glob)
131 $LOCALIP - - [$LOGDATE$] "GET http://localhost:$HGPORT2/?cmd=capabilities HTTP/1.1" 404 - (glob)
@@ -1,223 +1,219 b''
1 1 #!/usr/bin/env python
2 2
3 3 from __future__ import absolute_import, print_function
4 4
5 5 __doc__ = """Tiny HTTP Proxy.
6 6
7 7 This module implements GET, HEAD, POST, PUT and DELETE methods
8 8 on BaseHTTPServer, and behaves as an HTTP proxy. The CONNECT
9 9 method is also implemented experimentally, but has not been
10 10 tested yet.
11 11
12 12 Any help will be greatly appreciated. SUZUKI Hisao
13 13 """
14 14
15 15 __version__ = "0.2.1"
16 16
17 17 import optparse
18 18 import os
19 19 import select
20 20 import socket
21 21 import sys
22 22
23 23 from mercurial import (
24 24 pycompat,
25 25 util,
26 26 )
27 27
28 28 httpserver = util.httpserver
29 29 socketserver = util.socketserver
30 30 urlreq = util.urlreq
31 31
32 32 if os.environ.get('HGIPV6', '0') == '1':
33 33 family = socket.AF_INET6
34 34 else:
35 35 family = socket.AF_INET
36 36
37 37
38 38 class ProxyHandler(httpserver.basehttprequesthandler):
39 39 __base = httpserver.basehttprequesthandler
40 40 __base_handle = __base.handle
41 41
42 42 server_version = "TinyHTTPProxy/" + __version__
43 43 rbufsize = 0 # self.rfile Be unbuffered
44 44
45 45 def handle(self):
46 46 (ip, port) = self.client_address
47 47 allowed = getattr(self, 'allowed_clients', None)
48 48 if allowed is not None and ip not in allowed:
49 49 self.raw_requestline = self.rfile.readline()
50 50 if self.parse_request():
51 51 self.send_error(403)
52 52 else:
53 53 self.__base_handle()
54 54
55 55 def log_request(self, code='-', size='-'):
56 56 xheaders = [h for h in self.headers.items() if h[0].startswith('x-')]
57 57 self.log_message(
58 58 '"%s" %s %s%s',
59 59 self.requestline,
60 60 str(code),
61 61 str(size),
62 62 ''.join([' %s:%s' % h for h in sorted(xheaders)]),
63 63 )
64 64 # Flush for Windows, so output isn't lost on TerminateProcess()
65 65 sys.stdout.flush()
66 66 sys.stderr.flush()
67 67
68 68 def _connect_to(self, netloc, soc):
69 69 i = netloc.find(':')
70 70 if i >= 0:
71 71 host_port = netloc[:i], int(netloc[i + 1 :])
72 72 else:
73 73 host_port = netloc, 80
74 74 print("\t" "connect to %s:%d" % host_port)
75 75 try:
76 76 soc.connect(host_port)
77 except socket.error as arg:
78 try:
79 msg = arg[1]
80 except (IndexError, TypeError):
81 msg = arg
82 self.send_error(404, msg)
77 except socket.error as e:
78 self.send_error(404, e.strerror)
83 79 return 0
84 80 return 1
85 81
86 82 def do_CONNECT(self):
87 83 soc = socket.socket(family, socket.SOCK_STREAM)
88 84 try:
89 85 if self._connect_to(self.path, soc):
90 86 self.log_request(200)
91 87 self.wfile.write(
92 88 pycompat.bytestr(self.protocol_version)
93 89 + b" 200 Connection established\r\n"
94 90 )
95 91 self.wfile.write(
96 92 b"Proxy-agent: %s\r\n"
97 93 % pycompat.bytestr(self.version_string())
98 94 )
99 95 self.wfile.write(b"\r\n")
100 96 self._read_write(soc, 300)
101 97 finally:
102 98 print("\t" "bye")
103 99 soc.close()
104 100 self.connection.close()
105 101
106 102 def do_GET(self):
107 103 (scm, netloc, path, params, query, fragment) = urlreq.urlparse(
108 104 self.path, 'http'
109 105 )
110 106 if scm != 'http' or fragment or not netloc:
111 107 self.send_error(400, "bad url %s" % self.path)
112 108 return
113 109 soc = socket.socket(family, socket.SOCK_STREAM)
114 110 try:
115 111 if self._connect_to(netloc, soc):
116 112 self.log_request()
117 113 url = urlreq.urlunparse(('', '', path, params, query, ''))
118 114 soc.send(
119 115 b"%s %s %s\r\n"
120 116 % (
121 117 pycompat.bytestr(self.command),
122 118 pycompat.bytestr(url),
123 119 pycompat.bytestr(self.request_version),
124 120 )
125 121 )
126 122 self.headers['Connection'] = 'close'
127 123 del self.headers['Proxy-Connection']
128 124 for key, val in self.headers.items():
129 125 soc.send(
130 126 b"%s: %s\r\n"
131 127 % (pycompat.bytestr(key), pycompat.bytestr(val))
132 128 )
133 129 soc.send(b"\r\n")
134 130 self._read_write(soc)
135 131 finally:
136 132 print("\t" "bye")
137 133 soc.close()
138 134 self.connection.close()
139 135
140 136 def _read_write(self, soc, max_idling=20):
141 137 iw = [self.connection, soc]
142 138 ow = []
143 139 count = 0
144 140 while True:
145 141 count += 1
146 142 (ins, _, exs) = select.select(iw, ow, iw, 3)
147 143 if exs:
148 144 break
149 145 if ins:
150 146 for i in ins:
151 147 if i is soc:
152 148 out = self.connection
153 149 else:
154 150 out = soc
155 151 try:
156 152 data = i.recv(8192)
157 153 except socket.error:
158 154 break
159 155 if data:
160 156 out.send(data)
161 157 count = 0
162 158 else:
163 159 print("\t" "idle", count)
164 160 if count == max_idling:
165 161 break
166 162
167 163 do_HEAD = do_GET
168 164 do_POST = do_GET
169 165 do_PUT = do_GET
170 166 do_DELETE = do_GET
171 167
172 168
173 169 class ThreadingHTTPServer(socketserver.ThreadingMixIn, httpserver.httpserver):
174 170 def __init__(self, *args, **kwargs):
175 171 httpserver.httpserver.__init__(self, *args, **kwargs)
176 172 a = open("proxy.pid", "w")
177 173 a.write(str(os.getpid()) + "\n")
178 174 a.close()
179 175
180 176
181 177 def runserver(port=8000, bind=""):
182 178 server_address = (bind, port)
183 179 ProxyHandler.protocol_version = "HTTP/1.0"
184 180 httpd = ThreadingHTTPServer(server_address, ProxyHandler)
185 181 sa = httpd.socket.getsockname()
186 182 print("Serving HTTP on", sa[0], "port", sa[1], "...")
187 183 try:
188 184 httpd.serve_forever()
189 185 except KeyboardInterrupt:
190 186 print("\nKeyboard interrupt received, exiting.")
191 187 httpd.server_close()
192 188 sys.exit(0)
193 189
194 190
195 191 if __name__ == '__main__':
196 192 argv = sys.argv
197 193 if argv[1:] and argv[1] in ('-h', '--help'):
198 194 print(argv[0], "[port [allowed_client_name ...]]")
199 195 else:
200 196 if argv[2:]:
201 197 allowed = []
202 198 for name in argv[2:]:
203 199 client = socket.gethostbyname(name)
204 200 allowed.append(client)
205 201 print("Accept: %s (%s)" % (client, name))
206 202 ProxyHandler.allowed_clients = allowed
207 203 del argv[2:]
208 204 else:
209 205 print("Any clients will be served...")
210 206
211 207 parser = optparse.OptionParser()
212 208 parser.add_option(
213 209 '-b',
214 210 '--bind',
215 211 metavar='ADDRESS',
216 212 help='Specify alternate bind address ' '[default: all interfaces]',
217 213 default='',
218 214 )
219 215 (options, args) = parser.parse_args()
220 216 port = 8000
221 217 if len(args) == 1:
222 218 port = int(args[0])
223 219 runserver(port, options.bind)
General Comments 0
You need to be logged in to leave comments. Login now