hgweb: skip body creation of HEAD for most requests
The body is thrown away anyway, so this just wastes a lot of CPU time.
In the case of /archive/, this skips manifest processing and the actual
file archiving, resulting in a huge difference.
The most tricky part here is skipping the Content-Length creation as it
would indicate the output size for the corresponding GET request.
--- a/mercurial/hgweb/hgweb_mod.py Wed Jan 04 16:02:22 2023 +0100
+++ b/mercurial/hgweb/hgweb_mod.py Fri Dec 16 17:46:20 2022 +0100
@@ -230,8 +230,9 @@
def sendtemplate(self, name, **kwargs):
"""Helper function to send a response generated from a template."""
- kwargs = pycompat.byteskwargs(kwargs)
- self.res.setbodygen(self.tmpl.generate(name, kwargs))
+ if self.req.method != b'HEAD':
+ kwargs = pycompat.byteskwargs(kwargs)
+ self.res.setbodygen(self.tmpl.generate(name, kwargs))
return self.res.sendresponse()
--- a/mercurial/hgweb/request.py Wed Jan 04 16:02:22 2023 +0100
+++ b/mercurial/hgweb/request.py Fri Dec 16 17:46:20 2022 +0100
@@ -485,6 +485,7 @@
self._bodybytes is None
and self._bodygen is None
and not self._bodywillwrite
+ and self._req.method != b'HEAD'
):
raise error.ProgrammingError(b'response body not defined')
@@ -594,6 +595,8 @@
yield chunk
elif self._bodywillwrite:
self._bodywritefn = write
+ elif self._req.method == b'HEAD':
+ pass
else:
error.ProgrammingError(b'do not know how to send body')
--- a/mercurial/hgweb/server.py Wed Jan 04 16:02:22 2023 +0100
+++ b/mercurial/hgweb/server.py Fri Dec 16 17:46:20 2022 +0100
@@ -151,6 +151,9 @@
def do_GET(self):
self.do_POST()
+ def do_HEAD(self):
+ self.do_POST()
+
def do_hgweb(self):
self.sent_headers = False
path, query = _splitURI(self.path)
@@ -246,7 +249,11 @@
self.send_header(*h)
if h[0].lower() == 'content-length':
self.length = int(h[1])
- if self.length is None and saved_status[0] != common.HTTP_NOT_MODIFIED:
+ if (
+ self.length is None
+ and saved_status[0] != common.HTTP_NOT_MODIFIED
+ and self.command != 'HEAD'
+ ):
self._chunked = (
not self.close_connection and self.request_version == 'HTTP/1.1'
)
--- a/mercurial/hgweb/webcommands.py Wed Jan 04 16:02:22 2023 +0100
+++ b/mercurial/hgweb/webcommands.py Fri Dec 16 17:46:20 2022 +0100
@@ -1299,6 +1299,9 @@
b'sendresponse() should not emit data if writing later'
)
+ if web.req.method == b'HEAD':
+ return []
+
bodyfh = web.res.getbodyfile()
archival.archive(