Projet

Général

Profil

Bug #40799

crash sur accès URL catégorie sans / final et avec query string

Ajouté par Frédéric Péters il y a environ 4 ans. Mis à jour il y a environ 4 ans.

Statut:
Fermé
Priorité:
Normal
Assigné à:
-
Catégorie:
-
Version cible:
-
Début:
17 mars 2020
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:
Non

Description

Exception:
  type = '<class 'AssertionError'>', value = ''

Stack trace (most recent call first):
  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/quixote/directory.py", line 75, in _q_traverse
    73         Traverse a path and return the result.
    74         """ 
>   75         assert len(path) > 0
    76         component = path[0]
    77         path = path[1:]

  locals: 
     path = []
     self = <modules.formpage.AlternateFormsRootDirectory object at 0x7f6518a3a710>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/quixote/directory.py", line 116, in _q_traverse
   114     def _q_traverse(self, path):
   115         self._q_access()
>  116         return super(AccessControlled, self)._q_traverse(path)
   117 
   118 

  locals: 
     __class__ = <class 'quixote.directory.AccessControlled'>
     path = []
     self = <modules.formpage.AlternateFormsRootDirectory object at 0x7f6518a3a710>

  File "../auquotidien/auquotidien/modules/root.py", line 292, in _q_traverse
   290                 return FormsRootDirectory(cat)._q_traverse(path[1:])
   291 
>  292             raise e
   293 
   294 

  locals: 
     base_url = '/'
     f = <FormDef 'seniors' id:295>
     path = ['seniors']
     response = <wcs.qommon.http_response.HTTPResponse object at 0x7f6518fa0710>
     self = <modules.root.AlternateRootDirectory object at 0x7f6519856c50>
     uri_rest = 'seniors?d=s'

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/quixote/publish.py", line 241, in try_publish
   239                 permanent=True)
   240         components = path[1:].split('/')
>  241         output = self.root_directory._q_traverse(components)
   242         # The callable ran OK, commit any changes to the session
   243         self.finish_successful_request()

  locals: 
     allowed_methods = ['GET', 'HEAD', 'POST']
     components = ['seniors']
     method = 'GET'
     path = '/seniors'
     request = <wcs.compat.CompatHTTPRequest object at 0x7f6519856c10>
     self = <wcs.compat.CompatWcsPublisher object at 0x7f6519856ad0>

  File "/home/fred/src/eo/wcs/wcs/compat.py", line 203, in process_request
   201             output = self.finish_interrupted_request(exc)
   202         except Exception as exc:
>  203             output = self.finish_failed_request()
   204         response = request.response
   205 

  locals: 
     exc = AssertionError()
     request = <wcs.compat.CompatHTTPRequest object at 0x7f6519856c10>
     self = <wcs.compat.CompatWcsPublisher object at 0x7f6519856ad0>

  File "/home/fred/src/eo/wcs/wcs/compat.py", line 242, in quixote
   240 def quixote(request):
   241     pub = get_publisher()
>  242     return pub.process_request(pub.get_request())
   243 
   244 

  locals: 
     pub = <wcs.compat.CompatWcsPublisher object at 0x7f6519856ad0>
     request = <WSGIRequest: GET '/seniors?d=s'>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/handlers/base.py", line 185, in _get_response
   183             wrapped_callback = self.make_view_atomic(callback)
   184             try:
>  185                 response = wrapped_callback(request, *callback_args, **callback_kwargs)
   186             except Exception as e:
   187                 response = self.process_exception_by_middleware(e, request)

  locals: 
     callback = <function quixote at 0x7f651f69e950>
     callback_args = ()
     callback_kwargs = {}
     request = <WSGIRequest: GET '/seniors?d=s'>
     resolver = <RegexURLResolver 'wcs.urls' (None:None) ^/>
     resolver_match = ResolverMatch(func=wcs.compat.quixote, args=(), kwargs={}, url_name=quixote, app_names=[], namespaces=[])
     response = None
     self = <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>
     wrapped_callback = <function quixote at 0x7f651f69e950>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/handlers/base.py", line 249, in _legacy_get_response
   247 
   248         if response is None:
>  249             response = self._get_response(request)
   250         return response

  locals: 
     middleware_method = <bound method PublisherInitialisationMiddleware.process_request of <wcs.middleware.PublisherInitialisationMiddleware object at 0x7f6519863390>>
     request = <WSGIRequest: GET '/seniors?d=s'>
     response = None
     self = <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/handlers/exception.py", line 41, in inner
    39     def inner(request):
    40         try:
>   41             response = get_response(request)
    42         except Exception as exc:
    43             response = response_for_exception(request, exc)

  locals: 
     get_response = <bound method BaseHandler._legacy_get_response of <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>>
     request = <WSGIRequest: GET '/seniors?d=s'>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/handlers/base.py", line 124, in get_response
   122         set_urlconf(settings.ROOT_URLCONF)
   123 
>  124         response = self._middleware_chain(request)
   125 
   126         # This block is only needed for legacy MIDDLEWARE_CLASSES; if

  locals: 
     request = <WSGIRequest: GET '/seniors?d=s'>
     self = <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/handlers/wsgi.py", line 157, in __call__
   155         signals.request_started.send(sender=self.__class__, environ=environ)
   156         request = self.request_class(environ)
>  157         response = self.get_response(request)
   158 
   159         response._handler_class = self.__class__

  locals: 
     environ = {'GJS_DEBUG_TOPICS': 'JS ERROR;JS LOG', 'USER': 'fred', 'LC_TIME': 'C.UTF-8', 'WCS_SETTINGS_FILE': '/home/fred/src/eo/wcs/local_settings.py', 'XONSH_INTERACTIVE': 'True', 'SSH_AGENT_PID': '2091', 'XDG_SESSION_TYPE': 'x11', 'SHLVL': '2', 'HOME': '/home/fred', 'OLDPWD': '/home/fred', 'DESKTOP_SESSION': 'gnome-xorg', 'XONSHRC': '/etc/xonshrc:/home/fred/.config/xonsh/rc.xsh:/home/fred/.xonshrc', 'GTK_MODULES': 'gail:atk-bridge', 'LC_MONETARY': 'fr_BE.utf8', 'LOADED_RC_FILES': 'False,False,True', 'DBUS_SESSION_BUS_ADDRESS': 'unix:abstract=/tmp/dbus-CSMo0gamDb,guid=8d4c7846f0395443c05248955e4925f0', 'COLORTERM': 'truecolor', 'DEBEMAIL': 'fpeters@debian.org', 'XONSH_COLOR_STYLE': 'paraiso-dark', 'TMPDIR': '/tmp/.tmpfs/', 'DEBFULLNAME': 'Frederic Peters', 'LOGNAME': 'fred', 'CHANGE_LOG_NAME': 'Frederic Peters', 'SHELL_TYPE': 'prompt_toolkit2', '_': './run.sh', 'XDG_SESSION_CLASS': 'user', 'USERNAME': 'fred', 'XONSH_LOGIN': '1', 'TERM': 'screen.xterm-256color', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'HISTCONTROL': 'ignoreboth', 'WINDOWPATH': '2', 'BASH_COMPLETIONS': '/usr/share/bash-completion/bash_completion', 'PATH': '/home/fred/.local/bin/:/home/fred/.local/bin/:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games', 'SESSION_MANAGER': 'local/sofa:@/tmp/.ICE-unix/2032,unix/sofa:/tmp/.ICE-unix/2032', 'GDM_LANG': 'fr_BE.UTF-8', 'EMAIL': 'fpeters@0d.be', 'XDG_MENU_PREFIX': 'gnome-', 'GNOME_TERMINAL_SCREEN': '/org/gnome/Terminal/screen/b2675015_c2a8_4a58_a2bd_02f5820dafd7', 'XDG_RUNTIME_DIR': '/run/user/1000', 'DISPLAY': ':0', 'LANG': 'C.UTF-8', 'XDG_CURRENT_DESKTOP': 'GNOME', 'PYTHONSTARTUP': '/home/fred/.pyprofile.py', 'STY': '2639.pts-1.sofa', 'XDG_SESSION_DESKTOP': 'gnome-xorg', 'XAUTHORITY': '/run/user/1000/gdm/Xauthority', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'GNOME_TERMINAL_SERVICE': ':1.50', 'SSH_AUTH_SOCK': '/run/user/1000/keyring/ssh', 'SHELL': '/bin/bash', 'QT_ACCESSIBILITY': '1', 'GDMSESSION': 'gnome-xorg', 'LC_MEASUREMENT': 'fr_BE.utf8', 'WINDOW': '9', 'GPG_AGENT_INFO': '/run/user/1000/gnupg/S.gpg-agent:0:1', 'GJS_DEBUG_OUTPUT': 'stderr', 'PWD': '/home/fred/src/eo/wcs', 'PROJ_LIB': '/usr/share/proj', 'LC_ALL': 'C.UTF-8', 'XDG_DATA_DIRS': '/usr/share/gnome:/home/fred/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/', 'TERMCAP': 'SC|screen.xterm-256color|VT 100/ANSI X3.64 virtual terminal:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:li#34:co#144:am:xn:xv:LP:sr=\\EM:al=\\E[L:AL=\\E[%dL:cs=\\E[%i%d;%dr:dl=\\E[M:DL=\\E[%dM:dc=\\E[P:DC=\\E[%dP:im=\\E[4h:ei=\\E[4l:mi:IC=\\E[%d@:ks=\\E[?1h\\E=:ke=\\E[?1l\\E>:vi=\\E[?25l:ve=\\E[34h\\E[?25h:vs=\\E[34l:ti=\\E[?1049h:te=\\E[?1049l:us=\\E[4m:ue=\\E[24m:so=\\E[3m:se=\\E[23m:mb=\\E[5m:md=\\E[1m:mh=\\E[2m:mr=\\E[7m:me=\\E[m:ms:Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:vb=\\Eg:G0:as=\\E(0:ae=\\E(B:ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:po=\\E[5i:pf=\\E[4i:Km=\\E[M:k0=\\E[10~:k1=\\EOP:k2=\\EOQ:k3=\\EOR:k4=\\EOS:k5=\\E[15~:k6=\\E[17~:k7=\\E[18~:k8=\\E[19~:k9=\\E[20~:k;=\\E[21~:F1=\\E[23~:F2=\\E[24~:kB=\\E[Z:kh=\\E[1~:@1=\\E[1~:kH=\\E[4~:@7=\\E[4~:kN=\\E[6~:kP=\\E[5~:kI=\\E[2~:kD=\\E[3~:ku=\\EOA:kd=\\EOB:kr=\\EOC:kl=\\EOD:km:', 'XONSH_VERSION': '0.9.13', 'LC_NUMERIC': 'fr_BE.utf8', 'PYTHONPATH': '/home/fred/src/eo/wcs:', 'LC_PAPER': 'fr_BE.utf8', 'CHANGE_LOG_EMAIL_ADDRESS': 'fpeters@0d.be', 'DEBSIGN_KEYID': '7149147DF2F46AE03D556E3B2AE901E5C70218D2', 'VTE_VERSION': '5803', 'DJANGO_SETTINGS_MODULE': 'wcs.settings', 'TZ': 'Europe/Brussels', 'RUN_MAIN': 'true', 'SERVER_NAME': 'localhost', 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8500', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.0', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/seniors', 'QUERY_STRING': 'd=s', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': 'auquo.fred.local.0d.be', 'HTTP_X_REAL_IP': '127.0.0.1', 'HTTP_X_FORWARDED_FOR': '127.0.0.1', 'HTTP_X_FORWARDED_SSL': 'on', 'HTTP_X_FORWARDED_PROTOCOL': 'ssl', 'HTTP_X_FORWARDED_PROTO': 'https', 'HTTP_CONNECTION': 'close', 'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE': 'fr,en;q=0.7,es;q=0.3', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_DNT': '1', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_COOKIE': 'publik_portal_agent_url=https%3A%2F%2Fcombo-agent.fred.local.0d.be%2F; publik_portal_agent_title=Portail%20Agent; hasConsent=true; gadjo_sidepage_status=expanded; wcs-769502="49vYiUrTJga0RAoQNYoYNQ"; a2-opened-session-ea83cc=1', 'wsgi.input': <_io.BufferedReader name=4>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>}
     request = <WSGIRequest: GET '/seniors?d=s'>
     self = <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>
     start_response = <bound method BaseHandler.start_response of <django.core.servers.basehttp.ServerHandler object at 0x7f6519862350>>

  File "/usr/lib/python3.7/wsgiref/handlers.py", line 137, in run
   135         try:
   136             self.setup_environ()
>  137             self.result = application(self.environ, self.start_response)
   138             self.finish_response()
   139         except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError):

  locals: 
     application = <django.core.handlers.wsgi.WSGIHandler object at 0x7f651aa67fd0>
     self = <django.core.servers.basehttp.ServerHandler object at 0x7f6519862350>

  File "/home/fred/src/eo/venv3/lib/python3.7/site-packages/Django-1.11.17-py3.7.egg/django/core/servers/basehttp.py", line 155, in handle
   153         )
   154         handler.request_handler = self      # backpointer for logging
>  155         handler.run(self.server.get_app())
   156 
   157 

  locals: 
     handler = <django.core.servers.basehttp.ServerHandler object at 0x7f6519862350>
     self = <django.core.servers.basehttp.WSGIRequestHandler object at 0x7f6519863f50>

  File "/usr/lib/python3.7/socketserver.py", line 720, in __init__
   718         self.setup()
   719         try:
>  720             self.handle()
   721         finally:
   722             self.finish()

  locals: 
     client_address = ('127.0.0.1', 52538)
     request = <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8500), raddr=('127.0.0.1', 52538)>
     self = <django.core.servers.basehttp.WSGIRequestHandler object at 0x7f6519863f50>
     server = <django.core.servers.basehttp.WSGIServer object at 0x7f651a6c7850>

  File "/usr/lib/python3.7/socketserver.py", line 360, in finish_request
   358     def finish_request(self, request, client_address):
   359         """Finish one request by instantiating RequestHandlerClass.""" 
>  360         self.RequestHandlerClass(request, client_address, self)
   361 
   362     def shutdown_request(self, request):

  locals: 
     client_address = ('127.0.0.1', 52538)
     request = <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8500), raddr=('127.0.0.1', 52538)>
     self = <django.core.servers.basehttp.WSGIServer object at 0x7f651a6c7850>

  File "/usr/lib/python3.7/socketserver.py", line 650, in process_request_thread
   648         """ 
   649         try:
>  650             self.finish_request(request, client_address)
   651         except Exception:
   652             self.handle_error(request, client_address)

  locals: 
     client_address = ('127.0.0.1', 52538)
     request = <socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8500), raddr=('127.0.0.1', 52538)>
     self = <django.core.servers.basehttp.WSGIServer object at 0x7f651a6c7850>

  File "/usr/lib/python3.7/threading.py", line 870, in run
   868         try:
   869             if self._target:
>  870                 self._target(*self._args, **self._kwargs)
   871         finally:
   872             # Avoid a refcycle if the thread is running a function with

  locals: 
     self = <TenantAwareThread(Thread-1, started daemon 140072195880704)>

  File "/home/fred/src/eo/wcs/wcs/qommon/__init__.py", line 75, in run
    73         if self.publisher:
    74             self.publisher.set_in_thread()
>   75         super(TenantAwareThread, self).run()
    76 
    77 

  locals: 
     __class__ = <class 'wcs.qommon.TenantAwareThread'>
     self = <TenantAwareThread(Thread-1, started daemon 140072195880704)>

  File "/usr/lib/python3.7/threading.py", line 926, in _bootstrap_inner
   924 
   925             try:
>  926                 self.run()
   927             except SystemExit:
   928                 pass

  locals: 
     self = <TenantAwareThread(Thread-1, started daemon 140072195880704)>

  File "/usr/lib/python3.7/threading.py", line 890, in _bootstrap
   888         # if a non-daemonic encounters this, something else is wrong.
   889         try:
>  890             self._bootstrap_inner()
   891         except:
   892             if self._daemonic and _sys is None:

  locals: 
     self = <TenantAwareThread(Thread-1, started daemon 140072195880704)>

Form:
d               's'

...
PATH_INFO       '/seniors'

QUERY_STRING    'd=s'
REMOTE_ADDR     '127.0.0.1'
REMOTE_HOST     ''
REQUEST_METHOD  'GET'
RUN_MAIN        'true'
SCRIPT_NAME     ''
SERVER_NAME     'localhost'

Fichiers

Révisions associées

Révision 7012ca29 (diff)
Ajouté par Frédéric Péters il y a environ 4 ans

misc: fix category URLs with missing trailing slash and query string (#40799)

Révision 6483190d (diff)
Ajouté par Frédéric Péters il y a environ 4 ans

misc: fix category URLs with missing trailing slash and query string (#40799)

Historique

#1

Mis à jour par Frédéric Péters il y a environ 4 ans

#2

Mis à jour par Thomas Noël il y a environ 4 ans

Pas compris le "lose query string on purpose" ; tu peux m'éclairer ?

#3

Mis à jour par Frédéric Péters il y a environ 4 ans

On ne conserve pas la query string volontairement parce que ces URL sont mauvaises à la base et que l'exemple de crash reçu c'était un /nous-contacter?fbclid=IwAR0eFSvDZxpurD-DeMxWZb6JFqEOK3oUULnN_qCVmP_D3adh2AprvPFMMFg

#4

Mis à jour par Thomas Noël il y a environ 4 ans

  • Statut changé de Solution proposée à Solution validée

Frédéric Péters a écrit :

On ne conserve pas la query string volontairement parce que ces URL sont mauvaises à la base

Ca roule.

#5

Mis à jour par Frédéric Péters il y a environ 4 ans

  • Statut changé de Solution validée à Résolu (à déployer)
commit 7012ca290f850f748f439c16af6102f92532d5ab
Author: Frédéric Péters <fpeters@entrouvert.com>
Date:   Tue Mar 17 23:14:02 2020 +0100

    misc: fix category URLs with missing trailing slash and query string (#40799)
#6

Mis à jour par Frédéric Péters il y a environ 4 ans

  • Statut changé de Résolu (à déployer) à Solution déployée

Formats disponibles : Atom PDF