150 # Request body input stream. |
150 # Request body input stream. |
151 bodyfh = attr.ib() |
151 bodyfh = attr.ib() |
152 # WSGI environment dict, unmodified. |
152 # WSGI environment dict, unmodified. |
153 rawenv = attr.ib() |
153 rawenv = attr.ib() |
154 |
154 |
155 def parserequestfromenv(env, bodyfh, reponame=None, altbaseurl=None): |
155 def parserequestfromenv(env, reponame=None, altbaseurl=None): |
156 """Parse URL components from environment variables. |
156 """Parse URL components from environment variables. |
157 |
157 |
158 WSGI defines request attributes via environment variables. This function |
158 WSGI defines request attributes via environment variables. This function |
159 parses the environment variables into a data structure. |
159 parses the environment variables into a data structure. |
160 |
160 |
323 # this, since a consumer will either either value to determine how many |
323 # this, since a consumer will either either value to determine how many |
324 # bytes are available to read. |
324 # bytes are available to read. |
325 if 'CONTENT_LENGTH' in env and 'HTTP_CONTENT_LENGTH' not in env: |
325 if 'CONTENT_LENGTH' in env and 'HTTP_CONTENT_LENGTH' not in env: |
326 headers['Content-Length'] = env['CONTENT_LENGTH'] |
326 headers['Content-Length'] = env['CONTENT_LENGTH'] |
327 |
327 |
328 # TODO do this once we remove wsgirequest.inp, otherwise we could have |
328 bodyfh = env['wsgi.input'] |
329 # multiple readers from the underlying input stream. |
329 if 'Content-Length' in headers: |
330 #bodyfh = env['wsgi.input'] |
330 bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length'])) |
331 #if 'Content-Length' in headers: |
|
332 # bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length'])) |
|
333 |
331 |
334 return parsedrequest(method=env['REQUEST_METHOD'], |
332 return parsedrequest(method=env['REQUEST_METHOD'], |
335 url=fullurl, baseurl=baseurl, |
333 url=fullurl, baseurl=baseurl, |
336 advertisedurl=advertisedfullurl, |
334 advertisedurl=advertisedfullurl, |
337 advertisedbaseurl=advertisedbaseurl, |
335 advertisedbaseurl=advertisedbaseurl, |
576 'is a generator?') |
574 'is a generator?') |
577 |
575 |
578 assert self._bodywritefn |
576 assert self._bodywritefn |
579 return offsettrackingwriter(self._bodywritefn) |
577 return offsettrackingwriter(self._bodywritefn) |
580 |
578 |
581 class wsgirequest(object): |
|
582 """Higher-level API for a WSGI request. |
|
583 |
|
584 WSGI applications are invoked with 2 arguments. They are used to |
|
585 instantiate instances of this class, which provides higher-level APIs |
|
586 for obtaining request parameters, writing HTTP output, etc. |
|
587 """ |
|
588 def __init__(self, wsgienv, start_response, altbaseurl=None): |
|
589 version = wsgienv[r'wsgi.version'] |
|
590 if (version < (1, 0)) or (version >= (2, 0)): |
|
591 raise RuntimeError("Unknown and unsupported WSGI version %d.%d" |
|
592 % version) |
|
593 |
|
594 inp = wsgienv[r'wsgi.input'] |
|
595 |
|
596 if r'HTTP_CONTENT_LENGTH' in wsgienv: |
|
597 inp = util.cappedreader(inp, int(wsgienv[r'HTTP_CONTENT_LENGTH'])) |
|
598 elif r'CONTENT_LENGTH' in wsgienv: |
|
599 inp = util.cappedreader(inp, int(wsgienv[r'CONTENT_LENGTH'])) |
|
600 |
|
601 self.err = wsgienv[r'wsgi.errors'] |
|
602 self.threaded = wsgienv[r'wsgi.multithread'] |
|
603 self.multiprocess = wsgienv[r'wsgi.multiprocess'] |
|
604 self.run_once = wsgienv[r'wsgi.run_once'] |
|
605 self.env = wsgienv |
|
606 self.req = parserequestfromenv(wsgienv, inp, altbaseurl=altbaseurl) |
|
607 self.res = wsgiresponse(self.req, start_response) |
|
608 |
|
609 def wsgiapplication(app_maker): |
579 def wsgiapplication(app_maker): |
610 '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() |
580 '''For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() |
611 can and should now be used as a WSGI application.''' |
581 can and should now be used as a WSGI application.''' |
612 application = app_maker() |
582 application = app_maker() |
613 def run_wsgi(env, respond): |
583 def run_wsgi(env, respond): |