emmett-framework / granian

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

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

Closed AngelicosPhosphoros closed 10 months ago

AngelicosPhosphoros commented 10 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 10 months ago

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

gi0baro commented 10 months ago

Fixed in master and 0.7.5