8 |
8 |
9 from mercurial.demandload import demandload |
9 from mercurial.demandload import demandload |
10 import os, sys, errno |
10 import os, sys, errno |
11 demandload(globals(), "urllib BaseHTTPServer socket SocketServer") |
11 demandload(globals(), "urllib BaseHTTPServer socket SocketServer") |
12 demandload(globals(), "mercurial:ui,hg,util,templater") |
12 demandload(globals(), "mercurial:ui,hg,util,templater") |
13 demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:hgrequest") |
13 demandload(globals(), "hgweb_mod:hgweb hgwebdir_mod:hgwebdir request:wsgiapplication") |
14 from mercurial.i18n import gettext as _ |
14 from mercurial.i18n import gettext as _ |
15 |
15 |
16 def _splitURI(uri): |
16 def _splitURI(uri): |
17 """ Return path and query splited from uri |
17 """ Return path and query splited from uri |
18 |
18 |
22 if '?' in uri: |
22 if '?' in uri: |
23 path, query = uri.split('?', 1) |
23 path, query = uri.split('?', 1) |
24 else: |
24 else: |
25 path, query = uri, '' |
25 path, query = uri, '' |
26 return urllib.unquote(path), query |
26 return urllib.unquote(path), query |
|
27 |
|
28 class _error_logger(object): |
|
29 def __init__(self, handler): |
|
30 self.handler = handler |
|
31 def flush(self): |
|
32 pass |
|
33 def write(str): |
|
34 self.writelines(str.split('\n')) |
|
35 def writelines(seq): |
|
36 for msg in seq: |
|
37 self.handler.log_error("HG error: %s", msg) |
27 |
38 |
28 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler): |
39 class _hgwebhandler(object, BaseHTTPServer.BaseHTTPRequestHandler): |
29 def __init__(self, *args, **kargs): |
40 def __init__(self, *args, **kargs): |
30 self.protocol_version = 'HTTP/1.1' |
41 self.protocol_version = 'HTTP/1.1' |
31 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs) |
42 BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kargs) |
82 hval = self.headers.getheader(header) |
93 hval = self.headers.getheader(header) |
83 hval = hval.replace('\n', '').strip() |
94 hval = hval.replace('\n', '').strip() |
84 if hval: |
95 if hval: |
85 env[hkey] = hval |
96 env[hkey] = hval |
86 env['SERVER_PROTOCOL'] = self.request_version |
97 env['SERVER_PROTOCOL'] = self.request_version |
87 |
98 env['wsgi.version'] = (1, 0) |
88 req = hgrequest(self.rfile, self.wfile, env) |
99 env['wsgi.url_scheme'] = 'http' |
89 self.send_response(200, "Script output follows") |
100 env['wsgi.input'] = self.rfile |
90 self.close_connection = self.server.make_and_run_handler(req) |
101 env['wsgi.errors'] = _error_logger(self) |
|
102 env['wsgi.multithread'] = isinstance(self.server, |
|
103 SocketServer.ThreadingMixIn) |
|
104 env['wsgi.multiprocess'] = isinstance(self.server, |
|
105 SocketServer.ForkingMixIn) |
|
106 env['wsgi.run_once'] = 0 |
|
107 |
|
108 self.close_connection = True |
|
109 self.saved_status = None |
|
110 self.saved_headers = [] |
|
111 self.sent_headers = False |
|
112 req = self.server.reqmaker(env, self._start_response) |
|
113 for data in req: |
|
114 if data: |
|
115 self._write(data) |
|
116 |
|
117 def send_headers(self): |
|
118 if not self.saved_status: |
|
119 raise AssertionError("Sending headers before start_response() called") |
|
120 saved_status = self.saved_status.split(None, 1) |
|
121 saved_status[0] = int(saved_status[0]) |
|
122 self.send_response(*saved_status) |
|
123 for h in self.saved_headers: |
|
124 self.send_header(*h) |
|
125 self.end_headers() |
|
126 self.sent_headers = True |
|
127 |
|
128 def _start_response(self, http_status, headers, exc_info=None): |
|
129 code, msg = http_status.split(None, 1) |
|
130 code = int(code) |
|
131 self.saved_status = http_status |
|
132 self.saved_headers = headers |
|
133 return self._write |
|
134 |
|
135 def _write(self, data): |
|
136 if not self.saved_status: |
|
137 raise AssertionError("data written before start_response() called") |
|
138 elif not self.sent_headers: |
|
139 self.send_headers() |
|
140 self.wfile.write(data) |
|
141 self.wfile.flush() |
91 |
142 |
92 def create_server(ui, repo): |
143 def create_server(ui, repo): |
93 use_threads = True |
144 use_threads = True |
94 |
145 |
95 def openlog(opt, default): |
146 def openlog(opt, default): |
125 self.errorlog = errorlog |
176 self.errorlog = errorlog |
126 self.repo = repo |
177 self.repo = repo |
127 self.webdir_conf = webdir_conf |
178 self.webdir_conf = webdir_conf |
128 self.webdirmaker = hgwebdir |
179 self.webdirmaker = hgwebdir |
129 self.repoviewmaker = hgweb |
180 self.repoviewmaker = hgweb |
130 |
181 self.reqmaker = wsgiapplication(self.make_handler) |
131 def make_and_run_handler(self, req): |
182 |
|
183 def make_handler(self): |
132 if self.webdir_conf: |
184 if self.webdir_conf: |
133 hgwebobj = self.webdirmaker(self.webdir_conf) |
185 hgwebobj = self.webdirmaker(self.webdir_conf) |
134 elif self.repo is not None: |
186 elif self.repo is not None: |
135 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui, |
187 hgwebobj = self.repoviewmaker(repo.__class__(repo.ui, |
136 repo.origroot)) |
188 repo.origroot)) |
137 else: |
189 else: |
138 raise hg.RepoError(_('no repo found')) |
190 raise hg.RepoError(_('no repo found')) |
139 hgwebobj.run(req) |
191 return hgwebobj |
140 return req.will_close |
|
141 |
192 |
142 class IPv6HTTPServer(MercurialHTTPServer): |
193 class IPv6HTTPServer(MercurialHTTPServer): |
143 address_family = getattr(socket, 'AF_INET6', None) |
194 address_family = getattr(socket, 'AF_INET6', None) |
144 |
195 |
145 def __init__(self, *args, **kwargs): |
196 def __init__(self, *args, **kwargs): |