emmett-framework / granian

A Rust HTTP server for Python applications
BSD 3-Clause "New" or "Revised" License
2.67k stars 79 forks source link

Mercurial hgweb throws an exception due to passing port as int #169

Closed AngelicosPhosphoros closed 8 months ago

AngelicosPhosphoros commented 8 months ago

It work using other WSGI servers, e.g. gunicorn or pyruvate.

It happens because Mercurial tries to concatenate provided port (which is int) to bytes object from environ. I don't know if this is granian bug or Mercurial bug.

Details:

OS: Alpine Linux 3.19 (https://hub.docker.com/layers/library/alpine/3.19.0/) Software versions

# python --version
Python 3.11.6
# granian --version
granian 0.7.4
hg --version
....
Mercurial Distributed SCM (version 6.6)

hgweb.conf

[paths]
/ = /var/somedir_rw/*

[web]
baseurl = /
allow_push = *
push_ssl = false

hgwsgi.py

import traceback
config = b'/opt/priv_hg/hgweb.conf'
from mercurial import demandimport
demandimport.enable()
from mercurial.hgweb import hgweb

hg = hgweb(config)

def application(environ, start_response):
 try:
   return hg(environ, start_response)
 except Exception as err:
   print(type(err))
   print(repr(err))
   print(traceback.format_exc())
   raise

Command used to execute:

granian --host 0.0.0.0 --port 8003 --interface wsgi --http 1 --no-ws hgwsgi:application --log --log-level debug --opt

Traceback:

[WARNING] Application callable raised an exception
<class 'TypeError'>
TypeError("can't concat int to bytes")
Traceback (most recent call last):
  File "/opt/priv_hg/hgwsgi.py", line 11, in application
    return hg(environ, start_response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mercurial/hgweb/hgwebdir_mod.py", line 376, in __call__
    req = requestmod.parserequestfromenv(env, altbaseurl=baseurl)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mercurial/hgweb/request.py", line 224, in parserequestfromenv
    advertisedfullurl = addport(advertisedfullurl, env[b'SERVER_PORT'])
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/mercurial/hgweb/request.py", line 199, in addport
    s += b':' + port
         ~~~~~^~~~~~
TypeError: can't concat int to bytes
AngelicosPhosphoros commented 8 months ago

PEP 333 has such string concatenation of port to string in examples: https://peps.python.org/pep-0333/#url-reconstruction

gi0baro commented 8 months ago

Fixed in master and 0.7.5