##// END OF EJS Templates
hgweb: use compression engine API for zlib compression...
Gregory Szorc -
r30358:38130a0b default
parent child Browse files
Show More
@@ -1,133 +1,127 b''
1 #
1 #
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import cgi
10 import cgi
11 import zlib
11 import zlib
12
12
13 from .common import (
13 from .common import (
14 HTTP_OK,
14 HTTP_OK,
15 )
15 )
16
16
17 from .. import (
17 from .. import (
18 util,
18 util,
19 wireproto,
19 wireproto,
20 )
20 )
21 stringio = util.stringio
21 stringio = util.stringio
22
22
23 urlerr = util.urlerr
23 urlerr = util.urlerr
24 urlreq = util.urlreq
24 urlreq = util.urlreq
25
25
26 HGTYPE = 'application/mercurial-0.1'
26 HGTYPE = 'application/mercurial-0.1'
27 HGERRTYPE = 'application/hg-error'
27 HGERRTYPE = 'application/hg-error'
28
28
29 class webproto(wireproto.abstractserverproto):
29 class webproto(wireproto.abstractserverproto):
30 def __init__(self, req, ui):
30 def __init__(self, req, ui):
31 self.req = req
31 self.req = req
32 self.response = ''
32 self.response = ''
33 self.ui = ui
33 self.ui = ui
34 def getargs(self, args):
34 def getargs(self, args):
35 knownargs = self._args()
35 knownargs = self._args()
36 data = {}
36 data = {}
37 keys = args.split()
37 keys = args.split()
38 for k in keys:
38 for k in keys:
39 if k == '*':
39 if k == '*':
40 star = {}
40 star = {}
41 for key in knownargs.keys():
41 for key in knownargs.keys():
42 if key != 'cmd' and key not in keys:
42 if key != 'cmd' and key not in keys:
43 star[key] = knownargs[key][0]
43 star[key] = knownargs[key][0]
44 data['*'] = star
44 data['*'] = star
45 else:
45 else:
46 data[k] = knownargs[k][0]
46 data[k] = knownargs[k][0]
47 return [data[k] for k in keys]
47 return [data[k] for k in keys]
48 def _args(self):
48 def _args(self):
49 args = self.req.form.copy()
49 args = self.req.form.copy()
50 postlen = int(self.req.env.get('HTTP_X_HGARGS_POST', 0))
50 postlen = int(self.req.env.get('HTTP_X_HGARGS_POST', 0))
51 if postlen:
51 if postlen:
52 args.update(cgi.parse_qs(
52 args.update(cgi.parse_qs(
53 self.req.read(postlen), keep_blank_values=True))
53 self.req.read(postlen), keep_blank_values=True))
54 return args
54 return args
55 chunks = []
55 chunks = []
56 i = 1
56 i = 1
57 while True:
57 while True:
58 h = self.req.env.get('HTTP_X_HGARG_' + str(i))
58 h = self.req.env.get('HTTP_X_HGARG_' + str(i))
59 if h is None:
59 if h is None:
60 break
60 break
61 chunks += [h]
61 chunks += [h]
62 i += 1
62 i += 1
63 args.update(cgi.parse_qs(''.join(chunks), keep_blank_values=True))
63 args.update(cgi.parse_qs(''.join(chunks), keep_blank_values=True))
64 return args
64 return args
65 def getfile(self, fp):
65 def getfile(self, fp):
66 length = int(self.req.env['CONTENT_LENGTH'])
66 length = int(self.req.env['CONTENT_LENGTH'])
67 for s in util.filechunkiter(self.req, limit=length):
67 for s in util.filechunkiter(self.req, limit=length):
68 fp.write(s)
68 fp.write(s)
69 def redirect(self):
69 def redirect(self):
70 self.oldio = self.ui.fout, self.ui.ferr
70 self.oldio = self.ui.fout, self.ui.ferr
71 self.ui.ferr = self.ui.fout = stringio()
71 self.ui.ferr = self.ui.fout = stringio()
72 def restore(self):
72 def restore(self):
73 val = self.ui.fout.getvalue()
73 val = self.ui.fout.getvalue()
74 self.ui.ferr, self.ui.fout = self.oldio
74 self.ui.ferr, self.ui.fout = self.oldio
75 return val
75 return val
76
76
77 def groupchunks(self, fh):
77 def groupchunks(self, fh):
78 def getchunks():
78 def getchunks():
79 while True:
79 while True:
80 chunk = fh.read(32768)
80 chunk = fh.read(32768)
81 if not chunk:
81 if not chunk:
82 break
82 break
83 yield chunk
83 yield chunk
84
84
85 return self.compresschunks(getchunks())
85 return self.compresschunks(getchunks())
86
86
87 def compresschunks(self, chunks):
87 def compresschunks(self, chunks):
88 # Don't allow untrusted settings because disabling compression or
88 # Don't allow untrusted settings because disabling compression or
89 # setting a very high compression level could lead to flooding
89 # setting a very high compression level could lead to flooding
90 # the server's network or CPU.
90 # the server's network or CPU.
91 z = zlib.compressobj(self.ui.configint('server', 'zliblevel', -1))
91 opts = {'level': self.ui.configint('server', 'zliblevel', -1)}
92 for chunk in chunks:
92 return util.compengines['zlib'].compressstream(chunks, opts)
93 data = z.compress(chunk)
94 # Not all calls to compress() emit data. It is cheaper to inspect
95 # that here than to send it via the generator.
96 if data:
97 yield data
98 yield z.flush()
99
93
100 def _client(self):
94 def _client(self):
101 return 'remote:%s:%s:%s' % (
95 return 'remote:%s:%s:%s' % (
102 self.req.env.get('wsgi.url_scheme') or 'http',
96 self.req.env.get('wsgi.url_scheme') or 'http',
103 urlreq.quote(self.req.env.get('REMOTE_HOST', '')),
97 urlreq.quote(self.req.env.get('REMOTE_HOST', '')),
104 urlreq.quote(self.req.env.get('REMOTE_USER', '')))
98 urlreq.quote(self.req.env.get('REMOTE_USER', '')))
105
99
106 def iscmd(cmd):
100 def iscmd(cmd):
107 return cmd in wireproto.commands
101 return cmd in wireproto.commands
108
102
109 def call(repo, req, cmd):
103 def call(repo, req, cmd):
110 p = webproto(req, repo.ui)
104 p = webproto(req, repo.ui)
111 rsp = wireproto.dispatch(repo, p, cmd)
105 rsp = wireproto.dispatch(repo, p, cmd)
112 if isinstance(rsp, str):
106 if isinstance(rsp, str):
113 req.respond(HTTP_OK, HGTYPE, body=rsp)
107 req.respond(HTTP_OK, HGTYPE, body=rsp)
114 return []
108 return []
115 elif isinstance(rsp, wireproto.streamres):
109 elif isinstance(rsp, wireproto.streamres):
116 req.respond(HTTP_OK, HGTYPE)
110 req.respond(HTTP_OK, HGTYPE)
117 return rsp.gen
111 return rsp.gen
118 elif isinstance(rsp, wireproto.pushres):
112 elif isinstance(rsp, wireproto.pushres):
119 val = p.restore()
113 val = p.restore()
120 rsp = '%d\n%s' % (rsp.res, val)
114 rsp = '%d\n%s' % (rsp.res, val)
121 req.respond(HTTP_OK, HGTYPE, body=rsp)
115 req.respond(HTTP_OK, HGTYPE, body=rsp)
122 return []
116 return []
123 elif isinstance(rsp, wireproto.pusherr):
117 elif isinstance(rsp, wireproto.pusherr):
124 # drain the incoming bundle
118 # drain the incoming bundle
125 req.drain()
119 req.drain()
126 p.restore()
120 p.restore()
127 rsp = '0\n%s\n' % rsp.res
121 rsp = '0\n%s\n' % rsp.res
128 req.respond(HTTP_OK, HGTYPE, body=rsp)
122 req.respond(HTTP_OK, HGTYPE, body=rsp)
129 return []
123 return []
130 elif isinstance(rsp, wireproto.ooberror):
124 elif isinstance(rsp, wireproto.ooberror):
131 rsp = rsp.message
125 rsp = rsp.message
132 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
126 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
133 return []
127 return []
General Comments 0
You need to be logged in to leave comments. Login now